has('dir')) { $dir = $request->dir; // Security checks... $currentDir = "${baseDir}/${dir}"; } // Get file listings $contents = scandir($currentDir); $fileData = []; foreach ($contents as $item) { if ($item !== "." && $item !== "..") { $path = $currentDir . '/' . $item; $isDir = is_dir($path); if (!$isDir) { // Try to find file in database to get tags $fileModel = File::where('filename', $item)->first(); $tags = $fileModel ? $fileModel->tags : collect(); } else { $tags = collect(); } // Build file info $fileData[] = [ 'name' => $item, 'path' => $path, 'is_dir' => $isDir, 'size' => $isDir ? 0 : filesize($path), 'modified' => filemtime($path), 'extension' => $isDir ? '' : pathinfo($item, PATHINFO_EXTENSION), 'tags' => $tags ]; } } // Get all available tags for the tagging UI $allTags = Tag::orderBy('label')->get(); return view('files.index', compact('fileData', 'allTags', 'currentDir')); } /** * Store a newly created file in storage. */ public function store(Request $request) { $dir = 'uploads'; if ($request->has('current_dir')) { // Extract relative directory path if provided $dir = str_replace('storage/', '', $request->current_dir); } // Validate files $maxsize = config('filesystems.max_upload_size', 10240); // Default to 10MB $validated = $request->validate([ 'f' => "required|array|max:${maxsize}", 'f.*' => "required|file|max:${maxsize}" ]); $results = [ 'num_files' => count($request->file('f')), 'num_uploaded' => 0, 'files' => [] ]; // Process tags $tags = []; if ($request->has('tags') && !empty($request->tags)) { $tags = array_map('trim', explode(',', $request->tags)); } foreach ($request->file('f') as $file) { $filename = $file->getClientOriginalName(); // Avoid duplicate filenames by adding timestamp if (Storage::disk('public')->exists("${dir}/${filename}")) { $filename = Carbon::now()->timestamp . '_' . $filename; } // Store the file $path = $file->storeAs($dir, $filename, 'public'); if ($path) { // Create file record in database $fileModel = File::create([ 'filename' => $filename, 'path' => $path, 'source' => $request->ip(), 'description' => '', 'md5' => md5_file($file->getRealPath()), 'size' => $file->getSize(), 'mime_type' => $file->getMimeType(), 'user_id' => Auth::id() ]); // Add tags if provided if (!empty($tags)) { $fileModel->addTags($tags); } $results['num_uploaded']++; $results['files'][] = [ 'filename' => $filename, 'path' => $path, 'id' => $fileModel->id ]; } } // Return based on requested response format if ($request->input('response_format') === 'html') { return redirect()->back()->with('success', "{$results['num_uploaded']} files uploaded successfully"); } return response()->json($results); } /** * Add tags to an existing file */ public function addTags(Request $request, $fileId) { $file = File::findOrFail($fileId); $validated = $request->validate([ 'tags' => 'required|string' ]); $tags = array_map('trim', explode(',', $validated['tags'])); $file->addTags($tags); if ($request->wantsJson()) { return response()->json([ 'success' => true, 'tags' => $file->tags ]); } return redirect()->back()->with('success', 'Tags added successfully'); } /** * Remove a tag from a file */ public function removeTag(Request $request, $fileId, $tagId) { $file = File::findOrFail($fileId); $tag = Tag::findOrFail($tagId); $file->tags()->detach($tagId); $tag->decrement('refs'); if ($request->wantsJson()) { return response()->json([ 'success' => true ]); } return redirect()->back()->with('success', 'Tag removed'); } /** * Display the specified file info */ public function show(File $file) { return view('files.show', compact('file')); } /** * Update the specified file's info */ public function update(Request $request, File $file) { $validated = $request->validate([ 'description' => 'nullable|string', 'tags' => 'nullable|string' ]); $file->description = $validated['description'] ?? $file->description; $file->save(); if (isset($validated['tags'])) { $tags = array_map('trim', explode(',', $validated['tags'])); $file->tags()->detach(); $file->addTags($tags); } return redirect()->back()->with('success', 'File updated successfully'); } /** * Remove the specified file */ public function destroy(File $file) { // Remove the file from storage if (Storage::disk('public')->exists($file->path)) { Storage::disk('public')->delete($file->path); } // Delete from database (will auto detach tags) $file->delete(); return redirect()->route('files.index')->with('success', 'File deleted successfully'); } /** * Download a file */ public function download($filename) { $file = File::where('filename', $filename)->first(); if (!$file) { // Try to find file in storage even if not in DB $path = 'uploads/' . $filename; if (Storage::disk('public')->exists($path)) { return Storage::disk('public')->download($path); } abort(404, 'File not found'); } return Storage::disk('public')->download($file->path); } /** * List files by tag */ public function byTag($tagId) { $tag = Tag::findOrFail($tagId); $files = $tag->files()->paginate(20); return view('files.by-tag', compact('tag', 'files')); } }