getFilename(); } $dbImagePaths = Image::pluck('path')->toArray(); // Add images from disk that are not in the database $imagesToAdd = array_diff($diskImagePaths, $dbImagePaths); foreach ($imagesToAdd as $path) { Image::create(['path' => $path]); } // Remove images from database that are not on disk $imagesToRemove = array_diff($dbImagePaths, $diskImagePaths); Image::whereIn('path', $imagesToRemove)->delete(); // Fetch all images from the database after synchronization $images = Image::orderBy('updated_at', 'desc')->get(); $formattedImages = []; foreach ($images as $image) { $formattedImages[] = [ 'image_id' => $image->id, 'path' => asset('storage/' . $image->path), 'name' => basename($image->path), 'is_temp' => (bool) $image->is_temp, ]; } return response()->json($formattedImages); } public function upload(Request $request) { $request->validate([ 'image' => 'required|image|max:10240', // Max 10MB ]); $file = $request->file('image'); $fileName = uniqid() . '.' . $file->getClientOriginalExtension(); $destinationPath = public_path('storage/uploads'); // Ensure the directory exists if (!File::exists($destinationPath)) { File::makeDirectory($destinationPath, 0755, true); } $file->move($destinationPath, $fileName); $relativePath = 'uploads/' . $fileName; // Path relative to public/storage/ $image = Image::create([ 'path' => $relativePath, ]); return response()->json([ 'message' => __('api.image_uploaded_successfully'), 'image_id' => $image->id, 'path' => asset('storage/' . $relativePath), ]); } public function styleChangeRequest(Request $request) { // Same-origin check $appUrl = config('app.url'); $referer = $request->headers->get('referer'); if ($referer && parse_url($referer, PHP_URL_HOST) !== parse_url($appUrl, PHP_URL_HOST)) { return response()->json(['error' => 'Unauthorized: Request must originate from the same domain.'], 403); } $request->validate([ 'image_id' => 'required|exists:images,id', 'style_id' => 'required|exists:styles,id', ]); $image = Image::find($request->image_id); $style = Style::with(['aiModel' => function ($query) { $query->where('enabled', true)->with(['apiProviders' => function ($query) { $query->where('enabled', true); }]); }])->find($request->style_id); if (!$style || !$style->aiModel || $style->aiModel->apiProviders->isEmpty()) { return response()->json(['error' => __('api.style_or_provider_not_found')], 404); } try { $apiProvider = $style->aiModel->apiProviders->first(); // Get the first enabled API provider if (!$apiProvider) { return response()->json(['error' => __('api.style_or_provider_not_found')], 404); } $plugin = PluginLoader::getPlugin($apiProvider->plugin, $apiProvider); $result = $plugin->processImageStyleChange( public_path('storage/' . $image->path), $style->prompt, $style->aiModel->model_id, $style->parameters ); $base64Image = $result['base64Data']; $decodedImage = base64_decode(preg_replace('#^data:image/\w+;base64, #i', '', $base64Image)); $newImageName = 'styled_' . uniqid() . '.png'; // Assuming PNG for now $newImagePathRelative = 'uploads/' . $newImageName; // Path relative to public/storage/ $newImageFullPath = public_path('storage/' . $newImagePathRelative); // Full path to save // Ensure the directory exists if (!File::exists(public_path('storage/uploads'))) { File::makeDirectory(public_path('storage/uploads'), 0755, true); } File::put($newImageFullPath, $decodedImage); // Save using File facade $newImage = Image::create([ 'path' => $newImagePathRelative, // Store relative path 'original_image_id' => $image->id, // Link to original image 'style_id' => $style->id, // Link to applied style 'is_temp' => true, // Mark as temporary until user keeps it ]); return response()->json([ 'message' => 'Style change successful', 'styled_image' => [ 'id' => $newImage->id, 'path' => asset('storage/' . $newImage->path), 'is_temp' => $newImage->is_temp, ], ]); } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 500); } } public function keepImage(Request $request) { $request->validate([ 'image_id' => 'required|exists:images,id', ]); $image = Image::find($request->image_id); if (!$image) { return response()->json(['error' => __('api.image_not_found')], 404); } $image->is_temp = false; $image->save(); return response()->json(['message' => __('api.image_kept_successfully')]); } public function deleteImage(Image $image) { try { // Delete from the public/storage directory File::delete(public_path('storage/' . $image->path)); $image->delete(); return response()->json(['message' => __('api.image_deleted_successfully')]); } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 500); } } public function getStatus(Request $request) { $request->validate([ 'image_id' => 'required|exists:images,id', 'api_provider_name' => 'required|string', ]); $image = Image::find($request->image_id); $apiProvider = ApiProvider::where('name', $request->api_provider_name)->first(); if (!$image || !$apiProvider) { return response()->json(['error' => __('api.image_or_provider_not_found')], 404); } try { $plugin = PluginLoader::getPlugin($apiProvider->name); $status = $plugin->getStatus($image->uuid); // Annahme: Image Model hat eine UUID return response()->json($status); } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 500); } } public function getProgress(Request $request) { $request->validate([ 'image_id' => 'required|exists:images,id', 'api_provider_name' => 'required|string', ]); $image = Image::find($request->image_id); $apiProvider = ApiProvider::where('name', $request->api_provider_name)->first(); if (!$image || !$apiProvider) { return response()->json(['error' => __('api.image_or_provider_not_found')], 404); } try { $plugin = PluginLoader::getPlugin($apiProvider->name); $progress = $plugin->getProgress($image->uuid); // Annahme: Image Model hat eine UUID return response()->json($progress); } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 500); } } }