app/Jobs/Avatars/MoveContactAvatarToPhotosDirectory.php (118 lines of code) (raw):
<?php
namespace App\Jobs\Avatars;
use App\Models\Account\Photo;
use Illuminate\Bus\Queueable;
use App\Events\MoveAvatarEvent;
use App\Models\Contact\Contact;
use Illuminate\Support\Facades\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use Illuminate\Queue\InteractsWithQueue;
use App\Exceptions\FileNotFoundException;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Services\Contact\Avatar\UpdateAvatar;
class MoveContactAvatarToPhotosDirectory implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* The number of times the job may be attempted.
*
* @var int
*/
public $tries = 1;
/**
* @var Contact
*/
private $contact;
/**
* @var bool
*/
private $dryrun;
/**
* @var \Illuminate\Contracts\Filesystem\Filesystem
*/
private $storage;
/**
* Create a new job instance.
*
* @param Contact $contact
* @param bool $dryrun
* @return void
*/
public function __construct(Contact $contact, $dryrun)
{
$this->contact = $contact;
$this->dryrun = $dryrun;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$this->storage = Storage::disk($this->contact->avatar_location);
// move avatar to new location
$avatarFileName = $this->moveContactAvatars();
if ($this->dryrun) {
return;
}
// create a Photo object for this avatar
$photo = $this->createPhotoObject($avatarFileName);
// associate the Photo object to the contact
$this->associatePhotoAsAvatar($photo);
// delete original avatar
$this->deleteOriginalAvatar($avatarFileName);
// delete thumbnails of avatars
$this->deleteThumbnails();
}
/**
* @return string|null
*/
private function moveContactAvatars(): ?string
{
Event::dispatch(new MoveAvatarEvent($this->contact));
$newStorage = Storage::disk(config('filesystems.default'));
$avatarFileName = $this->getAvatarFileName();
// $avatarFileName has the format `avatars/XXX.jpg`. We need to remove
// the `avatars/` string to store the new file.
$newAvatarFilename = str_replace('avatars/', 'photos/', $avatarFileName);
if ($newStorage->exists($newAvatarFilename)) {
return null;
}
if (! $this->dryrun) {
$avatarFile = $this->storage->get($avatarFileName);
$newStorage->put($newAvatarFilename, $avatarFile, 'public');
$this->contact->avatar_location = config('filesystems.default');
$this->contact->save();
}
return $avatarFileName;
}
/**
* @param string|null $avatarFileName
* @return Photo|null
*/
private function createPhotoObject($avatarFileName): ?Photo
{
if (is_null($avatarFileName)) {
return null;
}
$newAvatarFilename = str_replace('avatars/', '', $avatarFileName);
$photo = new Photo;
$photo->account_id = $this->contact->account_id;
$photo->original_filename = $newAvatarFilename;
$photo->new_filename = 'photos/'.$newAvatarFilename;
$photo->filesize = Storage::disk($this->contact->avatar_location)->size('/photos/'.$newAvatarFilename);
$photo->mime_type = 'adfad';
$photo->save();
return $photo;
}
private function associatePhotoAsAvatar($photo)
{
if (is_null($photo)) {
return;
}
$data = [
'account_id' => $this->contact->account_id,
'contact_id' => $this->contact->id,
'source' => 'photo',
'photo_id' => $photo->id,
];
app(UpdateAvatar::class)->execute($data);
}
private function deleteThumbnails()
{
try {
$smallThumbnail = $this->getAvatarFileName(110);
$this->storage->delete($smallThumbnail);
} catch (FileNotFoundException $e) {
// ignore
}
try {
$bigThumbnail = $this->getAvatarFileName(174);
$this->storage->delete($bigThumbnail);
} catch (FileNotFoundException $e) {
// ignore
}
}
private function deleteOriginalAvatar($avatarFileName)
{
$this->storage->delete($avatarFileName);
}
private function getAvatarFileName($size = null)
{
$filename = pathinfo($this->contact->avatar_file_name, PATHINFO_FILENAME);
$extension = pathinfo($this->contact->avatar_file_name, PATHINFO_EXTENSION);
$avatarFileName = 'avatars/'.$filename.'.'.$extension;
if (! is_null($size)) {
$avatarFileName = 'avatars/'.$filename.'_'.$size.'.'.$extension;
}
if (! $this->fileExists($avatarFileName)) {
throw new FileNotFoundException($avatarFileName);
}
return $avatarFileName;
}
private function fileExists($avatarFileName): bool
{
return $this->storage->exists($avatarFileName);
}
}