173 lines
9.1 KiB
PHP
173 lines
9.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Database\Seeders;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Database\Seeder;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use cPad\Plugins\News\Models\NewsArticle;
|
|
use cPad\Plugins\News\Models\NewsCategory;
|
|
use cPad\Plugins\News\Models\NewsTag;
|
|
|
|
final class NewsLaunchSeeder extends Seeder
|
|
{
|
|
public function run(): void
|
|
{
|
|
$author = User::query()->firstWhere('email', 'newsroom@skinbase.local');
|
|
|
|
if (! $author) {
|
|
$author = new User();
|
|
$author->forceFill([
|
|
'name' => 'Skinbase Editorial',
|
|
'username' => 'skinbaseeditorial',
|
|
'email' => 'newsroom@skinbase.local',
|
|
'password' => Hash::make('password'),
|
|
'role' => 'moderator',
|
|
])->save();
|
|
$author = User::query()->firstWhere('email', 'newsroom@skinbase.local');
|
|
}
|
|
|
|
if (! $author) {
|
|
return;
|
|
}
|
|
|
|
$categories = [
|
|
'platform' => $this->upsertCategory('Platform', 'platform', 'Product updates, roadmap notes, and feature launches.'),
|
|
'groups' => $this->upsertCategory('Groups', 'groups', 'Stories about collaborative publishing, teams, and shared identity.'),
|
|
'tutorials' => $this->upsertCategory('Tutorials', 'tutorials', 'Practical guides for getting more from Nova.'),
|
|
'spotlight' => $this->upsertCategory('Spotlight', 'spotlight', 'Featured creators, groups, and standout work.'),
|
|
'releases' => $this->upsertCategory('Releases', 'releases', 'Coverage for launches, drops, and project milestones.'),
|
|
];
|
|
|
|
$tags = [
|
|
'nova' => $this->upsertTag('Nova', 'nova'),
|
|
'tutorial' => $this->upsertTag('Tutorial', 'tutorial'),
|
|
'groups' => $this->upsertTag('Groups', 'groups'),
|
|
'release' => $this->upsertTag('Release', 'release'),
|
|
'spotlight' => $this->upsertTag('Spotlight', 'spotlight'),
|
|
'platform-update' => $this->upsertTag('Platform Update', 'platform-update'),
|
|
];
|
|
|
|
$articles = [
|
|
[
|
|
'slug' => 'welcome-to-skinbase-nova',
|
|
'title' => 'Welcome to Skinbase Nova',
|
|
'type' => NewsArticle::TYPE_PLATFORM_UPDATE,
|
|
'category' => $categories['platform'],
|
|
'excerpt' => 'A first look at the refreshed Skinbase experience and the editorial direction behind Nova.',
|
|
'content' => "# Welcome to Skinbase Nova\n\nSkinbase Nova brings publishing, discovery, Groups, and editorial storytelling into a single platform experience.\n\n## What is new\n\n- a dedicated newsroom\n- stronger creator identity surfaces\n- deeper internal linking across Groups, releases, and profiles\n- cleaner editorial publishing tools inside Studio\n\nNova is designed to feel active, curated, and connected to the people making the work.",
|
|
'tags' => [$tags['nova'], $tags['platform-update']],
|
|
'days_ago' => 10,
|
|
'featured' => true,
|
|
'pinned' => true,
|
|
],
|
|
[
|
|
'slug' => 'introducing-groups-in-nova',
|
|
'title' => 'Introducing Groups in Nova',
|
|
'type' => NewsArticle::TYPE_ANNOUNCEMENT,
|
|
'category' => $categories['groups'],
|
|
'excerpt' => 'Groups give collaborative identities a real home across publishing, releases, events, and project storytelling.',
|
|
'content' => "# Introducing Groups\n\nGroups let creators publish under a shared identity while still keeping contributor context visible.\n\n## Why it matters\n\nGroups are more than labels. They support:\n\n- shared publishing\n- releases and milestones\n- recruiting and discovery\n- public storytelling\n\nThat makes Nova feel much more alive than a simple profile-only platform.",
|
|
'tags' => [$tags['groups'], $tags['nova']],
|
|
'days_ago' => 9,
|
|
'featured' => true,
|
|
'pinned' => false,
|
|
],
|
|
[
|
|
'slug' => 'how-studio-works-in-nova',
|
|
'title' => 'How Studio Works in Nova',
|
|
'type' => NewsArticle::TYPE_TUTORIAL,
|
|
'category' => $categories['tutorials'],
|
|
'excerpt' => 'A practical walkthrough of drafts, scheduling, content editing, and publishing flow inside Studio.',
|
|
'content' => "# How Studio Works\n\nStudio is the control layer for publishing in Nova.\n\n## Start with drafts\n\nUse Studio to prepare content, tune metadata, and move work through review before publishing.\n\n## Move with intent\n\nThe best results come from treating Studio as a workflow, not just a form. Draft, refine, preview, then publish.",
|
|
'tags' => [$tags['tutorial'], $tags['nova']],
|
|
'days_ago' => 7,
|
|
'featured' => false,
|
|
'pinned' => false,
|
|
],
|
|
[
|
|
'slug' => 'how-to-upload-your-first-artwork',
|
|
'title' => 'How to Upload Your First Artwork',
|
|
'type' => NewsArticle::TYPE_TUTORIAL,
|
|
'category' => $categories['tutorials'],
|
|
'excerpt' => 'A short guide to cleaner uploads, stronger metadata, and better first impressions.',
|
|
'content' => "# Upload Your First Artwork\n\nA strong upload starts with the basics:\n\n- a clear title\n- a readable description\n- accurate categories and tags\n- a polished thumbnail or cover\n\nGood publishing habits make discovery, search, and editorial coverage work better for you.",
|
|
'tags' => [$tags['tutorial']],
|
|
'days_ago' => 6,
|
|
'featured' => false,
|
|
'pinned' => false,
|
|
],
|
|
[
|
|
'slug' => 'creator-spotlight-building-a-recognizable-profile',
|
|
'title' => 'Creator Spotlight: Building a Recognizable Profile',
|
|
'type' => NewsArticle::TYPE_SPOTLIGHT,
|
|
'category' => $categories['spotlight'],
|
|
'excerpt' => 'Profiles work better when identity, consistency, and a clear body of work all point in the same direction.',
|
|
'content' => "# Creator Spotlight\n\nGreat profiles are memorable because they feel intentional.\n\n## Strong profile signals\n\n- consistent visual identity\n- complete bio and links\n- a curated set of standout uploads\n- a clear publishing rhythm\n\nNova rewards clarity and consistency.",
|
|
'tags' => [$tags['spotlight']],
|
|
'days_ago' => 4,
|
|
'featured' => false,
|
|
'pinned' => false,
|
|
],
|
|
[
|
|
'slug' => 'release-roundup-whats-new-this-week',
|
|
'title' => 'Release Roundup: What\'s New This Week',
|
|
'type' => NewsArticle::TYPE_RELEASE,
|
|
'category' => $categories['releases'],
|
|
'excerpt' => 'A compact editorial roundup of recent launches, notable drops, and community momentum.',
|
|
'content' => "# Release Roundup\n\nThis week\'s standout launches show why Nova needs editorial context alongside uploads.\n\nRelease coverage helps people discover:\n\n- the work itself\n- the team behind it\n- related projects and collections\n- where the story continues next",
|
|
'tags' => [$tags['release'], $tags['spotlight']],
|
|
'days_ago' => 2,
|
|
'featured' => false,
|
|
'pinned' => false,
|
|
],
|
|
];
|
|
|
|
foreach ($articles as $article) {
|
|
$record = NewsArticle::query()->firstOrNew(['slug' => $article['slug']]);
|
|
$record->forceFill([
|
|
'title' => $article['title'],
|
|
'slug' => $article['slug'],
|
|
'excerpt' => $article['excerpt'],
|
|
'content' => $article['content'],
|
|
'author_id' => $author->id,
|
|
'category_id' => $article['category']->id,
|
|
'type' => $article['type'],
|
|
'status' => 'published',
|
|
'editorial_status' => NewsArticle::EDITORIAL_STATUS_PUBLISHED,
|
|
'published_at' => Carbon::now()->subDays($article['days_ago'])->setTime(10, 0),
|
|
'is_featured' => $article['featured'],
|
|
'is_pinned' => $article['pinned'],
|
|
'meta_title' => $article['title'],
|
|
'meta_description' => $article['excerpt'],
|
|
'deleted_at' => null,
|
|
])->save();
|
|
|
|
$record->tags()->sync(array_map(static fn (NewsTag $tag): int => (int) $tag->id, $article['tags']));
|
|
}
|
|
}
|
|
|
|
private function upsertCategory(string $name, string $slug, string $description): NewsCategory
|
|
{
|
|
return NewsCategory::query()->updateOrCreate(
|
|
['slug' => $slug],
|
|
[
|
|
'name' => $name,
|
|
'description' => $description,
|
|
'position' => 0,
|
|
'is_active' => true,
|
|
]
|
|
);
|
|
}
|
|
|
|
private function upsertTag(string $name, string $slug): NewsTag
|
|
{
|
|
return NewsTag::query()->updateOrCreate(
|
|
['slug' => $slug],
|
|
['name' => $name]
|
|
);
|
|
}
|
|
} |