2016-09-02 21:27:50 +01:00
< ? php
namespace App\Http\Controllers\Admin ;
2016-09-07 21:44:28 +01:00
use App\Album ;
2016-09-08 23:22:29 +01:00
use App\AlbumSources\IAlbumSource ;
use App\Facade\Image ;
use App\Facade\Theme ;
2019-07-09 22:03:54 +01:00
use App\Facade\UserConfig ;
2019-07-12 16:21:30 +01:00
use App\Helpers\AnalysisQueueHelper ;
2016-10-28 05:30:57 +01:00
use App\Helpers\FileHelper ;
2016-09-08 23:22:29 +01:00
use App\Helpers\ImageHelper ;
2016-09-05 12:56:13 +01:00
use App\Helpers\MiscHelper ;
2016-10-28 14:05:53 +01:00
use App\Http\Requests\UpdatePhotosBulkRequest ;
2017-09-10 10:24:15 +01:00
use App\Label ;
2016-09-02 21:27:50 +01:00
use App\Photo ;
2019-07-09 22:03:54 +01:00
use App\QueueItem ;
2016-09-08 23:22:29 +01:00
use App\Services\PhotoService ;
2019-07-09 22:03:54 +01:00
use App\Services\RabbitMQService ;
2019-07-12 16:21:30 +01:00
use App\Storage ;
2016-09-02 21:27:50 +01:00
use App\Upload ;
use App\UploadPhoto ;
2018-10-09 22:16:43 +01:00
use App\User ;
use App\UserActivity ;
2016-09-02 21:27:50 +01:00
use Illuminate\Http\Request ;
use App\Http\Controllers\Controller ;
use Illuminate\Http\UploadedFile ;
2016-09-07 21:44:28 +01:00
use Illuminate\Support\Facades\App ;
2016-09-11 07:19:11 +01:00
use Illuminate\Support\Facades\Auth ;
2016-09-22 07:34:18 +01:00
use Illuminate\Support\Facades\Log ;
2016-10-05 16:31:37 +01:00
use Illuminate\Support\Facades\View ;
2016-09-05 12:56:13 +01:00
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator ;
2016-09-02 22:00:42 +01:00
use Symfony\Component\HttpFoundation\File\File ;
2016-09-02 21:27:50 +01:00
class PhotoController extends Controller
{
2016-09-22 07:34:18 +01:00
public function __construct ()
{
2016-09-24 08:17:51 +01:00
$this -> middleware ([ 'auth' , 'max_post_size_exceeded' ]);
2016-10-05 16:31:37 +01:00
View :: share ( 'is_admin' , true );
2016-09-22 07:34:18 +01:00
}
2016-10-28 05:30:57 +01:00
public function analyse ( $photoId , $queue_token )
2016-09-08 23:22:29 +01:00
{
2017-04-15 09:41:15 +01:00
$this -> authorizeAccessToAdminPanel ();
2016-09-08 23:22:29 +01:00
/** @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
{
2019-07-09 23:05:22 +01:00
if ( UserConfig :: isImageProcessingQueueEnabled ())
{
// Find the last record that is analysing this photo
$photoQueueItem = QueueItem :: where ( 'photo_id' , $photo -> id )
-> orderBy ( 'queued_at' , 'desc' )
-> limit ( 1 )
-> first ();
2016-09-08 23:22:29 +01:00
2019-07-09 23:05:22 +01:00
$timeToWait = 60 ;
$timeWaited = 0 ;
$continueToMonitor = true ;
2018-10-09 22:16:43 +01:00
2019-07-09 23:05:22 +01:00
while ( $continueToMonitor && $timeWaited < $timeToWait )
{
$continueToMonitor = is_null ( $photoQueueItem -> completed_at );
if ( $continueToMonitor )
{
sleep ( 1 );
$timeWaited ++ ;
$photoQueueItem = QueueItem :: where ( 'id' , $photoQueueItem -> id ) -> first ();
$continueToMonitor = is_null ( $photoQueueItem -> completed_at );
}
}
$result [ 'is_successful' ] = ! is_null ( $photoQueueItem -> completed_at );
if ( ! $result [ 'is_successful' ])
{
$result [ 'message' ] = 'Timed out waiting for queue processing.' ;
}
2018-10-09 22:16:43 +01:00
}
2019-07-09 23:05:22 +01:00
else
{
/* IF CHANGING THIS LOGIC, ALSO CHECK ProcessQueueCommand::processPhotoAnalyseMessage */
$photoService = new PhotoService ( $photo );
$photoService -> analyse ( $queue_token );
// Log an activity record for the user's feed (remove an existing one as the date may have changed)
$this -> removeExistingActivityRecords ( $photo , 'photo.taken' );
2018-10-09 22:16:43 +01:00
2019-07-09 23:05:22 +01:00
if ( ! is_null ( $photo -> taken_at ))
{
// Log an activity record for the user's feed
$this -> createActivityRecord ( $photo , 'photo.taken' , $photo -> taken_at );
}
$result [ 'is_successful' ] = true ;
}
2016-09-08 23:22:29 +01:00
}
catch ( \Exception $ex )
{
$result [ 'is_successful' ] = false ;
$result [ 'message' ] = $ex -> getMessage ();
2017-09-16 09:02:25 +01:00
// Remove the photo if it cannot be analysed (only if there isn't currently a version of metadata)
2017-09-17 16:04:07 +01:00
$photo -> delete ();
2016-09-08 23:22:29 +01:00
}
return response () -> json ( $result );
}
2016-09-02 21:27:50 +01:00
/**
* 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 ()
{
//
}
2016-09-09 09:45:11 +01:00
/**
* Remove the specified resource from storage .
*
* @ param int $id
* @ return \Illuminate\Http\Response
*/
2016-10-05 05:02:47 +01:00
public function destroy ( Request $request , $id )
2016-09-09 09:45:11 +01:00
{
2017-04-15 09:41:15 +01:00
$this -> authorizeAccessToAdminPanel ();
2016-09-09 09:45:11 +01:00
2017-04-16 09:00:57 +01:00
$photo = $this -> loadPhoto ( $id , 'delete' );
2016-09-09 09:45:11 +01:00
2016-09-09 11:09:03 +01:00
$photoService = new PhotoService ( $photo );
$photoService -> delete ();
2016-09-09 09:45:11 +01:00
2016-10-05 05:02:47 +01:00
$request -> session () -> flash ( 'success' , trans ( 'admin.delete_photo_successful_message' , [ 'name' => $photo -> name ]));
2016-09-09 09:45:11 +01:00
}
2016-10-03 15:57:58 +01:00
public function flip ( $photoId , $horizontal , $vertical )
{
2017-04-15 09:41:15 +01:00
$this -> authorizeAccessToAdminPanel ();
2016-10-03 15:57:58 +01:00
2016-10-28 12:59:36 +01:00
settype ( $horizontal , 'boolean' );
settype ( $vertical , 'boolean' );
2016-10-03 15:57:58 +01:00
2017-04-16 09:00:57 +01:00
$photo = $this -> loadPhoto ( $photoId , 'manipulate' );
2016-10-03 15:57:58 +01:00
$photoService = new PhotoService ( $photo );
$photoService -> flip ( $horizontal , $vertical );
2018-10-09 22:16:43 +01:00
// Log an activity record for the user's feed
$this -> createActivityRecord ( $photo , 'photo.edited' );
2016-10-03 15:57:58 +01:00
}
2016-10-05 05:02:47 +01:00
public function move ( Request $request , $photoId )
{
2017-04-15 09:41:15 +01:00
$this -> authorizeAccessToAdminPanel ();
2016-10-05 05:02:47 +01:00
2017-04-16 09:00:57 +01:00
$photo = $this -> loadPhoto ( $photoId , 'manipulate' );
2016-10-05 05:02:47 +01:00
$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 ));
}
}
2017-09-17 16:04:07 +01:00
public function reAnalyse ( $id , $queue_token )
{
$this -> authorizeAccessToAdminPanel ();
/** @var Photo $photo */
$photo = $this -> loadPhoto ( $id );
$result = [ 'is_successful' => false , 'message' => '' ];
try
{
$photoService = new PhotoService ( $photo );
$photoService -> downloadOriginalToFolder ( FileHelper :: getQueuePath ( $queue_token ));
$photoService -> analyse ( $queue_token );
2018-10-09 22:16:43 +01:00
// Log an activity record for the user's feed (remove an existing one as the date may have changed)
$this -> removeExistingActivityRecords ( $photo , 'photo.taken' );
if ( ! is_null ( $photo -> taken_at ))
{
// Log an activity record for the user's feed
$this -> createActivityRecord ( $photo , 'photo.taken' , $photo -> taken_at );
}
2017-09-17 16:04:07 +01:00
$result [ 'is_successful' ] = true ;
}
catch ( \Exception $ex )
{
$result [ 'is_successful' ] = false ;
$result [ 'message' ] = $ex -> getMessage ();
// Unlike the analyse method, we don't remove the photo if it cannot be analysed
}
return response () -> json ( $result );
}
2016-09-09 09:45:11 +01:00
public function regenerateThumbnails ( $photoId )
{
2017-04-15 09:41:15 +01:00
$this -> authorizeAccessToAdminPanel ();
2016-09-09 09:45:11 +01:00
2017-04-16 09:00:57 +01:00
$photo = $this -> loadPhoto ( $photoId , 'change-metadata' );
2016-09-09 09:45:11 +01:00
$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 );
}
2016-09-08 23:22:29 +01:00
public function rotate ( $photoId , $angle )
{
2017-04-15 09:41:15 +01:00
$this -> authorizeAccessToAdminPanel ();
2016-09-08 23:22:29 +01:00
2017-04-16 09:00:57 +01:00
$photo = $this -> loadPhoto ( $photoId , 'manipulate' );
2016-09-08 23:22:29 +01:00
if ( $angle != 90 && $angle != 180 && $angle != 270 )
{
App :: aport ( 400 );
return null ;
}
$photoService = new PhotoService ( $photo );
$photoService -> rotate ( $angle );
2018-10-09 22:16:43 +01:00
// Log an activity record for the user's feed
$this -> createActivityRecord ( $photo , 'photo.edited' );
2016-09-08 23:22:29 +01:00
}
2016-09-02 21:27:50 +01:00
/**
* Store a newly created resource in storage .
*
* @ param \Illuminate\Http\Request $request
* @ return \Illuminate\Http\Response
*/
public function store ( Request $request )
{
2017-04-15 09:41:15 +01:00
$this -> authorizeAccessToAdminPanel ();
2016-09-02 21:27:50 +01:00
2016-09-05 12:01:30 +01:00
$photoFiles = $request -> files -> get ( 'photo' );
2016-09-02 21:27:50 +01:00
// Load the linked album
2017-04-16 09:00:57 +01:00
$album = $this -> loadAlbum ( $request -> get ( 'album_id' ), 'upload-photos' );
2016-09-22 07:34:18 +01:00
$isSuccessful = false ;
2016-09-02 21:27:50 +01:00
2016-10-28 05:30:57 +01:00
// Create the folder to hold the analysis results if not already present
$queueUid = $request -> get ( 'queue_token' );
if ( strlen ( $queueUid ) == 0 )
{
throw new \Exception ( 'No queue_token value was provided!' );
}
2019-07-12 16:21:30 +01:00
$queueStorage = AnalysisQueueHelper :: getStorageQueueSource ();
2016-10-28 05:30:57 +01:00
2016-09-05 12:01:30 +01:00
foreach ( $photoFiles as $photoFile )
{
$photoFile = UploadedFile :: createFromBase ( $photoFile );
2016-09-22 07:34:18 +01:00
if ( $photoFile -> getError () != UPLOAD_ERR_OK )
{
Log :: error ( 'Image upload failed.' , [ 'error' => $photoFile -> getError (), 'reason' => $photoFile -> getErrorMessage ()]);
}
else
{
2017-09-12 21:41:47 +01:00
if ( $request -> has ( 'photo_id' ))
{
// Photo ID provided (using the Replace Photo function) - use that record
$photo = Photo :: where ( 'id' , intval ( $request -> get ( 'photo_id' ))) -> first ();
2017-09-16 12:52:40 +01:00
$photo -> raw_exif_data = null ;
2017-09-12 21:41:47 +01:00
/** @var File $savedFile */
2019-07-12 16:21:30 +01:00
$queueFolder = FileHelper :: getQueuePath ( $queueUid );
2017-09-12 21:41:47 +01:00
$savedFile = FileHelper :: saveUploadedFile ( $photoFile , $queueFolder , $photo -> storage_file_name );
2018-10-09 22:16:43 +01:00
$this -> removeExistingActivityRecords ( $photo , 'photo.uploaded' );
$this -> removeExistingActivityRecords ( $photo , 'photo.taken' );
2019-07-12 16:21:30 +01:00
$photo -> file_name = $photoFile -> getClientOriginalName ();
$photo -> mime_type = $savedFile -> getMimeType ();
$photo -> file_size = $savedFile -> getSize ();
$photo -> storage_file_name = $savedFile -> getFilename ();
2017-09-12 21:41:47 +01:00
}
else
{
2019-07-12 16:21:30 +01:00
$queuedFileName = $queueStorage -> uploadToAnalysisQueue ( $photoFile , $queueUid );
$uploadedTempFile = new File ( $photoFile );
2017-09-12 21:41:47 +01:00
$photo = new Photo ();
$photo -> album_id = $album -> id ;
$photo -> user_id = Auth :: user () -> id ;
$photo -> name = pathinfo ( $photoFile -> getClientOriginalName (), PATHINFO_FILENAME );
2019-07-12 16:21:30 +01:00
$photo -> file_name = $photoFile -> getClientOriginalName ();
$photo -> mime_type = $uploadedTempFile -> getMimeType ();
$photo -> file_size = $uploadedTempFile -> getSize ();
$photo -> storage_file_name = basename ( $queuedFileName );
2017-09-12 21:41:47 +01:00
}
2016-09-22 07:34:18 +01:00
$photo -> is_analysed = false ;
$photo -> save ();
2018-10-09 22:16:43 +01:00
// Log an activity record for the user's feed
$this -> createActivityRecord ( $photo , 'photo.uploaded' );
2019-07-09 22:03:54 +01:00
// If queueing is enabled, store the photo in the queue now
if ( UserConfig :: isImageProcessingQueueEnabled ())
{
$queueItem = new QueueItem ([
'batch_reference' => $queueUid ,
'action_type' => 'photo.analyse' ,
'album_id' => $photo -> album_id ,
'photo_id' => $photo -> id ,
2019-07-10 14:31:04 +01:00
'user_id' => $this -> getUser () -> id ,
2019-07-09 22:03:54 +01:00
'queued_at' => new \DateTime ()
]);
$queueItem -> save ();
$rabbitmq = new RabbitMQService ();
$rabbitmq -> queueItem ( $queueItem );
}
2016-09-22 07:34:18 +01:00
$isSuccessful = true ;
}
2016-09-05 12:01:30 +01:00
}
2016-09-11 09:04:07 +01:00
if ( $request -> isXmlHttpRequest ())
{
2016-09-22 07:34:18 +01:00
return response () -> json ([ 'is_successful' => $isSuccessful ]);
2016-09-11 09:04:07 +01:00
}
else
{
return redirect ( route ( 'albums.analyse' , [
2016-10-28 05:30:57 +01:00
'id' => $album -> id ,
'queue_token' => $queueUid
2016-09-11 09:04:07 +01:00
]));
}
2016-09-05 12:56:13 +01:00
}
public function storeBulk ( Request $request )
{
2017-04-15 09:41:15 +01:00
$this -> authorizeAccessToAdminPanel ();
2016-09-05 12:56:13 +01:00
// Load the linked album
2016-09-08 23:22:29 +01:00
$album = $this -> loadAlbum ( $request -> get ( 'album_id' ));
2016-09-05 12:56:13 +01:00
2018-07-13 00:00:45 +01:00
if ( is_null ( $request -> files -> get ( 'archive' )))
{
$request -> session () -> flash ( 'error' , trans ( 'admin.upload_bulk_no_file' ));
return redirect ( route ( 'albums.show' , [ 'id' => $album -> id ]));
}
2016-09-24 08:17:51 +01:00
$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 ]));
}
2016-10-28 05:30:57 +01:00
// Create the folder to hold the analysis results if not already present
$queueUid = $request -> get ( 'queue_token' );
if ( strlen ( $queueUid ) == 0 )
{
throw new \Exception ( 'No queue_token value was provided!' );
}
$queueFolder = FileHelper :: getQueuePath ( $queueUid );
2016-09-05 12:56:13 +01:00
2016-09-05 14:06:41 +01:00
$mimeType = strtolower ( $archiveFile -> getMimeType ());
switch ( $mimeType )
2016-09-05 12:56:13 +01:00
{
case 'application/zip' :
$zip = new \ZipArchive ();
$zip -> open ( $archiveFile -> getPathname ());
2016-10-28 05:30:57 +01:00
$zip -> extractTo ( $queueFolder );
2016-09-05 12:56:13 +01:00
$zip -> close ();
2016-10-30 18:36:34 +00:00
@ unlink ( $archiveFile -> getPathname ());
2016-09-05 12:56:13 +01:00
break ;
2016-09-05 14:06:41 +01:00
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 ]));
2016-09-05 12:56:13 +01:00
}
2016-10-28 05:30:57 +01:00
$di = new \RecursiveDirectoryIterator ( $queueFolder , \RecursiveDirectoryIterator :: SKIP_DOTS );
2016-09-05 14:06:41 +01:00
$recursive = new \RecursiveIteratorIterator ( $di );
2016-09-05 12:56:13 +01:00
/** @var \SplFileInfo $fileInfo */
2016-09-05 14:06:41 +01:00
foreach ( $recursive as $fileInfo )
2016-09-05 12:56:13 +01:00
{
2016-09-05 14:06:41 +01:00
if ( $fileInfo -> isDir ())
{
2016-09-11 07:19:11 +01:00
if ( $fileInfo -> getFilename () == '__MACOSX' || substr ( $fileInfo -> getFilename (), 0 , 1 ) == '.' )
2016-09-08 23:22:29 +01:00
{
@ rmdir ( $fileInfo -> getPathname ());
}
continue ;
}
2016-10-30 18:36:34 +00:00
if ( substr ( $fileInfo -> getFilename (), 0 , 1 ) == '.' )
{
// Temporary/hidden file - skip
@ unlink ( $fileInfo -> getPathname ());
continue ;
}
2016-09-08 23:22:29 +01:00
$result = getimagesize ( $fileInfo -> getPathname ());
if ( $result === false )
{
// Not an image file - skip
@ unlink ( $fileInfo -> getPathname ());
2016-09-05 14:06:41 +01:00
continue ;
}
2016-09-05 12:56:13 +01:00
$photoFile = new File ( $fileInfo -> getPathname ());
/** @var File $savedFile */
2016-10-30 18:36:34 +00:00
$savedFile = FileHelper :: saveExtractedFile ( $photoFile , $queueFolder );
2016-09-05 12:56:13 +01:00
$photo = new Photo ();
$photo -> album_id = $album -> id ;
2016-09-11 07:19:11 +01:00
$photo -> user_id = Auth :: user () -> id ;
2016-09-06 19:47:25 +01:00
$photo -> name = pathinfo ( $photoFile -> getFilename (), PATHINFO_FILENAME );
$photo -> file_name = $photoFile -> getFilename ();
$photo -> storage_file_name = $savedFile -> getFilename ();
2016-09-05 12:56:13 +01:00
$photo -> mime_type = $savedFile -> getMimeType ();
$photo -> file_size = $savedFile -> getSize ();
2016-09-08 23:22:29 +01:00
$photo -> is_analysed = false ;
2016-09-05 12:56:13 +01:00
$photo -> save ();
2018-10-09 22:16:43 +01:00
// Log an activity record for the user's feed
// Log an activity record for the user's feed
$this -> createActivityRecord ( $photo , 'photo.uploaded' );
2016-09-05 12:56:13 +01:00
}
2016-09-08 23:22:29 +01:00
return redirect ( route ( 'albums.analyse' , [
2016-10-28 05:30:57 +01:00
'id' => $album -> id ,
'queue_token' => $queueUid
2016-09-05 12:01:30 +01:00
]));
2016-09-02 21:27:50 +01:00
}
/**
* 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 )
{
//
}
2016-10-28 14:05:53 +01:00
public function updateBulk ( UpdatePhotosBulkRequest $request , $albumId )
2016-09-07 21:44:28 +01:00
{
2017-04-15 09:41:15 +01:00
$this -> authorizeAccessToAdminPanel ();
2016-09-11 09:04:07 +01:00
2017-04-16 09:00:57 +01:00
$album = $this -> loadAlbum ( $albumId );
2016-09-07 21:44:28 +01:00
2017-04-16 09:00:57 +01:00
if ( $request -> has ( 'bulk-apply' ))
2016-10-05 14:49:44 +01:00
{
$numberChanged = $this -> applyBulkActions ( $request , $album );
}
else
{
$numberChanged = $this -> updatePhotoDetails ( $request , $album );
}
2019-07-10 14:31:04 +01:00
$request -> session () -> flash (
'success' ,
trans_choice (
UserConfig :: isImageProcessingQueueEnabled () ? 'admin.bulk_photos_changed_queued' : 'admin.bulk_photos_changed' ,
$numberChanged ,
[ 'number' => $numberChanged ]
)
);
2016-10-05 14:49:44 +01:00
2017-09-04 20:56:30 +01:00
return redirect ( route ( 'albums.show' , array ( 'id' => $albumId , 'page' => $request -> get ( 'page' , 1 ))));
2016-10-05 14:49:44 +01:00
}
private function applyBulkActions ( Request $request , Album $album )
{
2016-10-30 19:10:20 +00:00
$selectAllInAlbum = boolval ( $request -> get ( 'select-all-album' ));
$photosToProcess = [];
if ( $selectAllInAlbum )
2016-10-05 14:49:44 +01:00
{
2016-10-30 19:10:20 +00:00
foreach ( $album -> photos as $photo )
{
$photosToProcess [] = $photo ;
}
}
else
{
$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 ;
}
foreach ( $photoIds as $photoId )
{
/** @var Photo $photo */
$photo = $album -> photos () -> where ( 'id' , intval ( $photoId )) -> first ();
if ( is_null ( $photo ))
{
continue ;
}
$photosToProcess [] = $photo ;
}
2016-10-05 14:49:44 +01:00
}
2016-10-03 17:00:37 +01:00
$action = $request -> get ( 'bulk-action' );
$numberChanged = 0 ;
2019-07-10 14:31:04 +01:00
if ( UserConfig :: isImageProcessingQueueEnabled ())
2016-09-07 21:44:28 +01:00
{
2019-07-10 14:31:04 +01:00
$queueUid = MiscHelper :: randomString ();
foreach ( $photosToProcess as $photo )
2016-10-03 17:00:37 +01:00
{
2019-07-10 14:31:04 +01:00
$queueItem = new QueueItem ([
'batch_reference' => $queueUid ,
'action_type' => sprintf ( 'photo.bulk_action.%s' , strtolower ( $action )),
'album_id' => $photo -> album_id ,
'photo_id' => $photo -> id ,
'user_id' => $this -> getUser () -> id ,
'queued_at' => new \DateTime ()
]);
$queueItem -> save ();
$rabbitmq = new RabbitMQService ();
$rabbitmq -> queueItem ( $queueItem );
$numberChanged ++ ;
}
}
else
{
foreach ( $photosToProcess as $photo )
{
$changed = false ;
$photoService = new PhotoService ( $photo );
$doNotSave = false ;
/* IF CHANGING THIS LOGIC OR ADDING EXTRA case OPTIONS, ALSO CHECK ProcessQueueCommand::processQueueItem AND ProcessQueueCommand::processPhotoBulkActionMessage */
switch ( strtolower ( $action ))
{
case 'change_album' :
if ( Auth :: user () -> can ( 'change-metadata' , $photo ))
2017-04-16 09:00:57 +01:00
{
2019-07-10 14:31:04 +01:00
$newAlbumId = intval ( $request -> get ( 'new-album-id' ));
if ( $newAlbumId == $photo -> album_id )
{
// Photo already belongs to this album, don't move
continue 2 ;
}
$newAlbum = $this -> loadAlbum ( $newAlbumId , 'upload-photos' );
$photoService -> changeAlbum ( $newAlbum );
$changed = true ;
2017-04-16 09:00:57 +01:00
}
2019-07-10 14:31:04 +01:00
break ;
2017-04-16 09:00:57 +01:00
2019-07-10 14:31:04 +01:00
case 'delete' :
if ( Auth :: user () -> can ( 'delete' , $photo ))
{
$photoService -> delete ();
$doNotSave = true ;
$changed = true ;
}
break ;
2016-10-03 17:00:37 +01:00
2019-07-10 14:31:04 +01:00
case 'flip_both' :
if ( Auth :: user () -> can ( 'manipulate' , $photo ))
{
$photoService -> flip ( true , true );
$changed = true ;
}
break ;
2016-10-03 17:00:37 +01:00
2019-07-10 14:31:04 +01:00
case 'flip_horizontal' :
if ( Auth :: user () -> can ( 'manipulate' , $photo ))
{
$photoService -> flip ( true , false );
$changed = true ;
}
break ;
2016-10-03 17:00:37 +01:00
2019-07-10 14:31:04 +01:00
case 'flip_vertical' :
if ( Auth :: user () -> can ( 'manipulate' , $photo ))
{
$photoService -> flip ( false , true );
$changed = true ;
}
break ;
2016-10-03 17:00:37 +01:00
2019-07-10 14:31:04 +01:00
case 'refresh_thumbnails' :
if ( Auth :: user () -> can ( 'change-metadata' , $photo ))
{
$photoService -> regenerateThumbnails ();
$changed = true ;
}
break ;
2016-10-03 17:00:37 +01:00
2019-07-10 14:31:04 +01:00
case 'rotate_left' :
if ( Auth :: user () -> can ( 'manipulate' , $photo ))
{
$photoService -> rotate ( 90 );
$changed = true ;
}
break ;
2016-10-03 17:00:37 +01:00
2019-07-10 14:31:04 +01:00
case 'rotate_right' :
if ( Auth :: user () -> can ( 'manipulate' , $photo ))
{
$photoService -> rotate ( 270 );
$changed = true ;
}
break ;
}
2016-10-03 17:00:37 +01:00
2019-07-10 14:31:04 +01:00
if ( ! $doNotSave )
{
$photo -> save ();
}
2016-10-05 14:49:44 +01:00
2019-07-10 14:31:04 +01:00
if ( ! in_array ( strtolower ( $action ), [ 'delete' , 'refresh_thumbnails' , 'change_album' ]))
{
// Log an activity record for the user's feed
$this -> createActivityRecord ( $photo , 'photo.edited' );
}
2018-10-09 22:16:43 +01:00
2019-07-10 14:31:04 +01:00
if ( $changed )
{
$numberChanged ++ ;
}
2017-04-16 09:00:57 +01:00
}
2016-09-07 21:44:28 +01:00
}
2016-10-05 14:49:44 +01:00
return $numberChanged ;
2016-09-07 21:44:28 +01:00
}
2018-10-09 22:16:43 +01:00
private function createActivityRecord ( Photo $photo , $type , $activityDateTime = null )
{
if ( is_null ( $activityDateTime ))
{
$activityDateTime = new \DateTime ();
}
$userActivity = new UserActivity ();
$userActivity -> user_id = $this -> getUser () -> id ;
$userActivity -> activity_at = $activityDateTime ;
$userActivity -> type = $type ;
$userActivity -> photo_id = $photo -> id ;
$userActivity -> save ();
}
2016-09-08 23:22:29 +01:00
/**
* @ param $id
* @ return Album
*/
2017-04-16 09:00:57 +01:00
private function loadAlbum ( $id , $permission = 'edit' )
2016-09-08 23:22:29 +01:00
{
$album = Album :: where ( 'id' , intval ( $id )) -> first ();
if ( is_null ( $album ))
{
App :: abort ( 404 );
return null ;
}
2017-04-16 09:00:57 +01:00
$this -> authorize ( $permission , $album );
2016-09-08 23:22:29 +01:00
return $album ;
}
2016-10-05 14:49:44 +01:00
2017-04-16 09:00:57 +01:00
/**
* @ param $id
* @ param string | null $permission
* @ return Photo
*/
private function loadPhoto ( $id , $permission = null )
{
$photo = Photo :: where ( 'id' , intval ( $id )) -> first ();
if ( is_null ( $photo ))
{
App :: abort ( 404 );
return null ;
}
if ( ! is_null ( $permission ))
{
$this -> authorize ( $permission , $photo );
}
return $photo ;
}
2018-10-09 22:16:43 +01:00
private function removeExistingActivityRecords ( Photo $photo , $type )
{
$existingFeedRecords = UserActivity :: where ([
'user_id' => $this -> getUser () -> id ,
'photo_id' => $photo -> id ,
'type' => $type
]) -> get ();
foreach ( $existingFeedRecords as $existingFeedRecord )
{
$existingFeedRecord -> delete ();
}
}
2016-10-05 14:49:44 +01:00
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 ();
2017-04-16 09:00:57 +01:00
if ( is_null ( $photo ) || ! Auth :: user () -> can ( 'change-metadata' , $photo ))
2016-10-05 14:49:44 +01:00
{
continue ;
}
$photo -> fill ( $value );
2017-09-10 10:24:15 +01:00
// Update the photo labels
2017-09-10 12:40:24 +01:00
$labelString = trim ( $value [ 'labels' ]);
2017-09-10 10:24:15 +01:00
$photo -> labels () -> detach ();
2017-09-10 12:40:24 +01:00
if ( strlen ( $labelString ) > 0 )
2017-09-10 10:24:15 +01:00
{
2017-09-10 12:40:24 +01:00
app ( LabelController :: class ) -> applyLabelsToPhoto ( $photo , $labelString );
2017-09-10 10:24:15 +01:00
}
// Save all changes
2016-10-05 14:49:44 +01:00
$photo -> save ();
$numberChanged ++ ;
}
return $numberChanged ;
}
2016-09-02 21:27:50 +01:00
}