command->error("JSON directory not found: {$jsonPath}"); return; } // Get all JSON files except the schema file $jsonFiles = File::glob($jsonPath . '/*.json'); $jsonFiles = array_filter($jsonFiles, function ($file) { return !str_contains(basename($file), 'schema'); }); $this->command->info('Starting to seed categories from JSON files...'); $this->command->info('Found ' . count($jsonFiles) . ' JSON files to process.'); foreach ($jsonFiles as $jsonFile) { $this->processJsonFile($jsonFile); } $this->command->info('Category seeding completed successfully!'); } /** * Process a single JSON file */ private function processJsonFile(string $filePath): void { $fileName = basename($filePath); $this->command->info("Processing: {$fileName}"); try { // Read and decode JSON content $jsonContent = File::get($filePath); $data = json_decode($jsonContent, true); if (json_last_error() !== JSON_ERROR_NONE) { $this->command->error("Invalid JSON in file: {$fileName} - " . json_last_error_msg()); return; } // Validate JSON structure if (!isset($data['category'])) { $this->command->error("Missing 'category' key in file: {$fileName}"); return; } $categoryData = $data['category']; // Validate required fields if (!isset($categoryData['name']) || !isset($categoryData['description'])) { $this->command->error("Missing required fields (name/description) in file: {$fileName}"); return; } // Create main category $mainCategory = $this->createMainCategory($categoryData, $data); if (!$mainCategory) { $this->command->error("Failed to create main category for file: {$fileName}"); return; } // Create subcategories if (isset($categoryData['subcategories']) && is_array($categoryData['subcategories'])) { foreach ($categoryData['subcategories'] as $index => $subcategoryData) { if (!$this->createSubcategory($subcategoryData, $mainCategory, $data, $index)) { $this->command->warn("Failed to create subcategory at index {$index} for file: {$fileName}"); } } } $this->command->info("✓ Successfully processed: {$fileName}"); } catch (\Exception $e) { $this->command->error("Error processing {$fileName}: " . $e->getMessage()); Log::error("CategorySeeder error for {$fileName}", [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); } } /** * Create a main category */ private function createMainCategory(array $categoryData, array $originalData): ?Category { try { // Check if category already exists $existingCategory = Category::where('name', $categoryData['name']) ->whereNull('parent_id') ->first(); if ($existingCategory) { $this->command->warn("Main category '{$categoryData['name']}' already exists. Skipping..."); return $existingCategory; } // Create the main category $category = Category::create([ 'is_enabled' => true, 'name' => $categoryData['name'], 'description' => $categoryData['description'], 'subcategories' => $categoryData['subcategories'] ?? null, 'keywords' => $categoryData['keywords'] ?? null, 'meme_angles' => null, // Main categories don't have meme_angles 'sample_captions' => null, // Main categories don't have sample_captions 'payload' => $originalData, 'embedding' => CloudflareAI::getVectorEmbeddingBgeSmall($categoryData['name'] . " " . $categoryData['description']), ]); // Add keywords as tags if (isset($categoryData['keywords']) && is_array($categoryData['keywords'])) { $this->attachKeywordsAsTags($category, $categoryData['keywords']); } $this->command->line(" ✓ Created main category: {$category->name}"); return $category; } catch (\Exception $e) { $this->command->error("Error creating main category: " . $e->getMessage()); Log::error("Error creating main category", [ 'category_data' => $categoryData, 'error' => $e->getMessage() ]); return null; } } /** * Create a subcategory */ private function createSubcategory(array $subcategoryData, Category $parentCategory, array $originalData, int $index): ?Category { try { // Validate required subcategory fields if (!isset($subcategoryData['name']) || !isset($subcategoryData['description'])) { $this->command->warn("Subcategory at index {$index} missing required fields (name/description). Skipping..."); return null; } // Check if subcategory already exists $existingSubcategory = Category::where('name', $subcategoryData['name']) ->where('parent_id', $parentCategory->id) ->first(); if ($existingSubcategory) { $this->command->warn(" Subcategory '{$subcategoryData['name']}' already exists. Skipping..."); return $existingSubcategory; } // Create subcategory payload $subcategoryPayload = [ 'subcategory' => $subcategoryData, 'parent_category' => [ 'name' => $parentCategory->name, 'description' => $parentCategory->description ] ]; // Create the subcategory using the correct nested set method $subcategory = Category::create([ 'is_enabled' => false, 'name' => $subcategoryData['name'], 'description' => $subcategoryData['description'], 'meme_angles' => $subcategoryData['meme_angles'] ?? null, 'sample_captions' => $subcategoryData['sample_captions'] ?? null, 'keywords' => $subcategoryData['keywords'] ?? null, 'subcategories' => null, // Subcategories don't have subcategories 'payload' => $subcategoryPayload, 'parent_id' => $parentCategory->id, // Set parent_id directly 'embedding' => CloudflareAI::getVectorEmbeddingBgeSmall($subcategoryData['name'] . " " . $subcategoryData['description']), ]); // Add keywords as tags if (isset($subcategoryData['keywords']) && is_array($subcategoryData['keywords'])) { $this->attachKeywordsAsTags($subcategory, $subcategoryData['keywords']); } $this->command->line(" ✓ Created subcategory: {$subcategory->name}"); return $subcategory; } catch (\Exception $e) { $this->command->error("Error creating subcategory at index {$index}: " . $e->getMessage()); Log::error("Error creating subcategory", [ 'subcategory_data' => $subcategoryData, 'parent_id' => $parentCategory->id, 'error' => $e->getMessage() ]); return null; } } /** * Attach keywords as tags to a category */ private function attachKeywordsAsTags(Category $category, array $keywords): void { try { $category->attachTags($keywords, 'category'); } catch (\Exception $e) { $this->command->warn("Failed to attach tags to category '{$category->name}': " . $e->getMessage()); Log::warning("Failed to attach tags", [ 'category_id' => $category->id, 'keywords' => $keywords, 'error' => $e->getMessage() ]); } } }