145 lines
5.1 KiB
PHP
145 lines
5.1 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Console\Commands;
|
||
|
|
|
||
|
|
use Illuminate\Console\Command;
|
||
|
|
use Illuminate\Support\Facades\DB;
|
||
|
|
use Illuminate\Support\Facades\Storage;
|
||
|
|
use App\Models\Entry;
|
||
|
|
|
||
|
|
class ImportBlogs extends Command
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* The name and signature of the console command.
|
||
|
|
*
|
||
|
|
* @var string
|
||
|
|
*/
|
||
|
|
protected $signature = 'app:import-blogs';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The console command description.
|
||
|
|
*
|
||
|
|
* @var string
|
||
|
|
*/
|
||
|
|
protected $description = 'Command description';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Execute the console command.
|
||
|
|
*/
|
||
|
|
public function handle()
|
||
|
|
{
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
{
|
||
|
|
"id": 7,
|
||
|
|
"title": "Low/No Code FlowiseAI",
|
||
|
|
"slug": "lowno-code-flowiseai",
|
||
|
|
"content": "<p><img alt=\"\" src=\"http://127.0.0.1:8000/storage/99/ZsTHWAQRbdvgRUEwGmCIsm4TyChIjBwiY71VmnnR.webp\"/></p>\n<p>In <a href=\"https://flowiseai.com/\">FlowiseAI</a>, applications based on the JavaScript fork of LangChain are modeled in a 'no/low-code' environment. If you are coming from a closed source world, yet trying to implement devops principles this may fill you with fear, dread and uncertainty. FlowiseAI offers the advantage of using plain-text JSON files to represent each workflow. These files are easy to understand, open, and readily backup-able, unlike opaque proprietary binary formats\nThe data used at runtime and other component prerequisites like credentials are stored in the FlowiseAI data volume, which looks like this</p>\n<p><code>bash\nMode LastWriteTime ..... 8ZS1C0ZBB.webp",
|
||
|
|
"created_at": "2024-12-17 11:24:59",
|
||
|
|
"updated_at": "2024-12-17 12:53:54",
|
||
|
|
"category_id": 1,
|
||
|
|
"blog_date": "2024-02-26 00:00",
|
||
|
|
"is_featured": 0,
|
||
|
|
"published": 1
|
||
|
|
},
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
$filePath = '/home/user/projects/laravel/12/media_library/boring-astro-static/imported_database/blogs.json';
|
||
|
|
|
||
|
|
if (!file_exists($filePath)) {
|
||
|
|
$this->error("File not found: $filePath");
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
$jsonContent = file_get_contents($filePath);
|
||
|
|
$blogs = json_decode($jsonContent, true);
|
||
|
|
|
||
|
|
if (!$blogs) {
|
||
|
|
$this->error("Could not parse JSON file: $filePath");
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ($blogs as $blog) {
|
||
|
|
// Only process the blog with ID 51
|
||
|
|
if (($blog['id'] ?? null) !== 51) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$slug = $blog['slug'] ?? null;
|
||
|
|
$this->info("Processing blog ID: {$blog['id']} with slug: {$slug}");
|
||
|
|
// Check if the entry already exists
|
||
|
|
$existingEntry = Entry::where('slug', $slug)->first();
|
||
|
|
|
||
|
|
if ($existingEntry) {
|
||
|
|
// Update existing entry with cleaned content
|
||
|
|
$existingEntry->update([
|
||
|
|
'content' => $this->cleanHtmlForFilament($blog['content'] ?? ''),
|
||
|
|
'description' => $this->extractPlainTextFromHtml($blog['content'] ?? ''),
|
||
|
|
]);
|
||
|
|
$this->info("Updated content for: {$existingEntry->title}");
|
||
|
|
} else {
|
||
|
|
// Create new entry
|
||
|
|
Entry::create([
|
||
|
|
'title' => $blog['title'] ?? null,
|
||
|
|
'slug' => $slug,
|
||
|
|
'description' => $this->extractPlainTextFromHtml($blog['content'] ?? ''),
|
||
|
|
'is_published' => $blog['published'] ?? false,
|
||
|
|
'is_featured' => $blog['is_featured'] ?? false,
|
||
|
|
'published_at' => $blog['blog_date'] ?? null,
|
||
|
|
'content' => $this->cleanHtmlForFilament($blog['content'] ?? ''),
|
||
|
|
'category_id' => 1, // Default category
|
||
|
|
]);
|
||
|
|
$this->info("Created new entry: " . ($blog['title'] ?? 'Untitled'));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->info('Blogs imported successfully.');
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Extract plain text from HTML for description field
|
||
|
|
*/
|
||
|
|
private function extractPlainTextFromHtml(string $html): string
|
||
|
|
{
|
||
|
|
if (empty($html)) {
|
||
|
|
return '';
|
||
|
|
}
|
||
|
|
|
||
|
|
// Decode HTML entities and strip tags
|
||
|
|
$text = html_entity_decode(strip_tags($html));
|
||
|
|
|
||
|
|
// Clean up whitespace
|
||
|
|
$text = preg_replace('/\s+/', ' ', $text);
|
||
|
|
|
||
|
|
// Limit to reasonable length for description
|
||
|
|
return trim(substr($text, 0, 500));
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Clean HTML content for Filament rich editor
|
||
|
|
*/
|
||
|
|
private function cleanHtmlForFilament(string $html): string
|
||
|
|
{
|
||
|
|
if (empty($html)) {
|
||
|
|
return '';
|
||
|
|
}
|
||
|
|
|
||
|
|
// Convert escaped newlines to actual newlines
|
||
|
|
$html = str_replace(['\\n', '\\r\\n', '\\r'], "\n", $html);
|
||
|
|
|
||
|
|
// Decode HTML entities
|
||
|
|
$html = html_entity_decode($html, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||
|
|
|
||
|
|
// Clean up excessive whitespace but preserve paragraph structure
|
||
|
|
$html = preg_replace('/\s*\n\s*/', ' ', $html);
|
||
|
|
$html = preg_replace('/[ \t]+/', ' ', $html);
|
||
|
|
|
||
|
|
// Ensure paragraphs have proper spacing
|
||
|
|
$html = str_replace('</p><p>', '</p>' . "\n" . '<p>', $html);
|
||
|
|
|
||
|
|
return trim($html);
|
||
|
|
}
|
||
|
|
}
|