middleware(['auth', 'max_post_size_exceeded']); } public function analyse($photoId) { $this->authorize('admin-access'); /** @var Photo $photo */ $photo = Photo::where('id', intval($photoId))->first(); if (is_null($photo)) { App::abort(404); return null; } $result = ['is_successful' => false, 'message' => '']; try { $photoService = new PhotoService($photo); $photoService->analyse(); $result['is_successful'] = true; } catch (\Exception $ex) { $result['is_successful'] = false; $result['message'] = $ex->getMessage(); // Remove the photo if it cannot be analysed $photo->delete(); } return response()->json($result); } /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { // } /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { // } /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy(Request $request, $id) { $this->authorize('admin-access'); /** @var Photo $photo */ $photo = Photo::where('id', intval($id))->first(); if (is_null($photo)) { App::abort(404); return null; } $photoService = new PhotoService($photo); $photoService->delete(); $request->session()->flash('success', trans('admin.delete_photo_successful_message', ['name' => $photo->name])); } public function flip($photoId, $horizontal, $vertical) { $this->authorize('admin-access'); settype($direction, 'boolean'); $photo = Photo::where('id', intval($photoId))->first(); if (is_null($photo)) { App::abort(404); return null; } $photoService = new PhotoService($photo); $photoService->flip($horizontal, $vertical); } public function move(Request $request, $photoId) { $this->authorize('admin-access'); $photo = Photo::where('id', intval($photoId))->first(); if (is_null($photo)) { App::abort(404); } $newAlbum = Album::where('id', intval($request->get('new_album_id')))->first(); if (is_null($newAlbum)) { App::abort(404); } $messageData = ['name' => $photo->name, 'album' => $newAlbum->name]; if ($newAlbum->id == $photo->album_id) { $request->session()->flash('warning', trans('admin.move_failed_same_album', $messageData)); } else { $photoService = new PhotoService($photo); $photoService->changeAlbum($newAlbum); $request->session()->flash('success', trans('admin.move_successful_message', $messageData)); } } public function regenerateThumbnails($photoId) { $this->authorize('admin-access'); /** @var Photo $photo */ $photo = Photo::where('id', intval($photoId))->first(); if (is_null($photo)) { App::abort(404); return null; } $result = ['is_successful' => false, 'message' => '']; try { $photoService = new PhotoService($photo); $photoService->regenerateThumbnails(); $result['is_successful'] = true; } catch (\Exception $ex) { $result['is_successful'] = false; $result['message'] = $ex->getMessage(); } return response()->json($result); } public function rotate($photoId, $angle) { $this->authorize('admin-access'); $photo = Photo::where('id', intval($photoId))->first(); if (is_null($photo)) { App::abort(404); return null; } if ($angle != 90 && $angle != 180 && $angle != 270) { App::aport(400); return null; } $photoService = new PhotoService($photo); $photoService->rotate($angle); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $this->authorize('admin-access'); $photoFiles = $request->files->get('photo'); // Load the linked album $album = $this->loadAlbum($request->get('album_id')); $isSuccessful = false; foreach ($photoFiles as $photoFile) { $photoFile = UploadedFile::createFromBase($photoFile); if ($photoFile->getError() != UPLOAD_ERR_OK) { Log::error('Image upload failed.', ['error' => $photoFile->getError(), 'reason' => $photoFile->getErrorMessage()]); } else { /** @var File $savedFile */ $savedFile = $album->getAlbumSource()->saveUploadedPhoto($photoFile); $photo = new Photo(); $photo->album_id = $album->id; $photo->user_id = Auth::user()->id; $photo->name = pathinfo($photoFile->getClientOriginalName(), PATHINFO_FILENAME); $photo->file_name = $photoFile->getClientOriginalName(); $photo->storage_file_name = $savedFile->getFilename(); $photo->mime_type = $savedFile->getMimeType(); $photo->file_size = $savedFile->getSize(); $photo->is_analysed = false; $photo->save(); $isSuccessful = true; } } if ($request->isXmlHttpRequest()) { return response()->json(['is_successful' => $isSuccessful]); } else { return redirect(route('albums.analyse', [ 'id' => $album->id ])); } } public function storeBulk(Request $request) { $this->authorize('admin-access'); // Load the linked album $album = $this->loadAlbum($request->get('album_id')); $archiveFile = UploadedFile::createFromBase($request->files->get('archive')); if ($archiveFile->getError() != UPLOAD_ERR_OK) { Log::error('Bulk image upload failed.', ['error' => $archiveFile->getError(), 'reason' => $archiveFile->getErrorMessage()]); $request->session()->flash('error', $archiveFile->getErrorMessage()); return redirect(route('albums.show', ['id' => $album->id])); } // Create a temporary folder to hold the extracted files $tempFolder = sprintf('%s/btw_upload_%s', env('TEMP_FOLDER', '/tmp'), MiscHelper::randomString()); mkdir($tempFolder); $mimeType = strtolower($archiveFile->getMimeType()); switch ($mimeType) { case 'application/zip': $zip = new \ZipArchive(); $zip->open($archiveFile->getPathname()); $zip->extractTo($tempFolder); $zip->close(); break; default: $request->session()->flash('error', sprintf('The file type "%s" is not supported for bulk uploads.', $mimeType)); return redirect(route('albums.show', ['id' => $album->id])); } $di = new \RecursiveDirectoryIterator($tempFolder, \RecursiveDirectoryIterator::SKIP_DOTS); $recursive = new \RecursiveIteratorIterator($di); /** @var \SplFileInfo $fileInfo */ foreach ($recursive as $fileInfo) { if ($fileInfo->isDir()) { if ($fileInfo->getFilename() == '__MACOSX' || substr($fileInfo->getFilename(), 0, 1) == '.') { @rmdir($fileInfo->getPathname()); } continue; } $result = getimagesize($fileInfo->getPathname()); if ($result === false) { // Not an image file - skip @unlink($fileInfo->getPathname()); continue; } $photoFile = new File($fileInfo->getPathname()); /** @var File $savedFile */ $savedFile = $album->getAlbumSource()->saveUploadedPhoto($photoFile); $photo = new Photo(); $photo->album_id = $album->id; $photo->user_id = Auth::user()->id; $photo->name = pathinfo($photoFile->getFilename(), PATHINFO_FILENAME); $photo->file_name = $photoFile->getFilename(); $photo->storage_file_name = $savedFile->getFilename(); $photo->mime_type = $savedFile->getMimeType(); $photo->file_size = $savedFile->getSize(); $photo->is_analysed = false; $photo->save(); } @rmdir($tempFolder); return redirect(route('albums.analyse', [ 'id' => $album->id ])); } /** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show($id) { // } /** * Show the form for editing the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function edit($id) { // } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { // } public function updateBulk(Request $request, $albumId) { $this->authorize('admin-access'); /** @var Album $album */ $album = Album::where('id', intval($albumId))->first(); if (is_null($album)) { App::abort(404); return null; } $numberChanged = 0; if ($request->has('bulk-apply')) { $numberChanged = $this->applyBulkActions($request, $album); } else { $numberChanged = $this->updatePhotoDetails($request, $album); } $request->session()->flash('success', trans_choice('admin.bulk_photos_changed', $numberChanged, ['number' => $numberChanged])); return redirect(route('albums.show', array('id' => $albumId))); } private function applyBulkActions(Request $request, Album $album) { $photoIds = $request->get('select-photo'); if (is_null($photoIds) || !is_array($photoIds) || count($photoIds) == 0) { $request->session()->flash('warning', trans('admin.no_photo_selected_message')); return 0; } $action = $request->get('bulk-action'); $numberChanged = 0; foreach ($photoIds as $photoId) { /** @var Photo $photo */ $photo = $album->photos()->where('id', intval($photoId))->first(); if (is_null($photo)) { continue; } $photoService = new PhotoService($photo); switch (strtolower($action)) { case 'change_album': $newAlbumId = intval($request->get('new-album-id')); if ($newAlbumId == $photo->album_id) { // Photo already belongs to this album, don't move continue; } $newAlbum = Album::where('id', $newAlbumId)->first(); if (is_null($newAlbum)) { App::abort(404); } $photoService->changeAlbum($newAlbum); break; case 'delete': $photoService->delete(); break; case 'flip_both': $photoService->flip(true, true); break; case 'flip_horizontal': $photoService->flip(true, false); break; case 'flip_vertical': $photoService->flip(false, true); break; case 'refresh_thumbnails': $photoService->regenerateThumbnails(); break; case 'rotate_left': $photoService->rotate(90); break; case 'rotate_right': $photoService->rotate(270); break; } $photo->save(); $numberChanged++; } return $numberChanged; } /** * @param $id * @return Album */ private function loadAlbum($id) { $album = Album::where('id', intval($id))->first(); if (is_null($album)) { App::abort(404); return null; } return $album; } private function updatePhotoDetails(Request $request, Album $album) { $numberChanged = 0; $photos = $request->get('photo'); foreach ($photos as $photoId => $value) { /** @var Photo $photo */ $photo = $album->photos()->where('id', intval($photoId))->first(); if (is_null($photo)) { continue; } $photo->fill($value); $photo->save(); $numberChanged++; } return $numberChanged; } }