Style tweaks to artworks DB

This commit is contained in:
Alex Cabal 2024-01-18 10:50:14 -06:00
parent 6e63bd2bdb
commit 2b5f4f55a2
5 changed files with 54 additions and 63 deletions

View file

@ -147,19 +147,4 @@ class Artist extends PropertiesBase{
where ArtistId = ? where ArtistId = ?
', [$this->ArtistId]); ', [$this->ArtistId]);
} }
public static function DeleteUnreferencedArtists(): void{
Db::Query('
DELETE
from Artists
where ArtistId NOT IN
(SELECT DISTINCT ArtistId FROM Artworks)
');
Db::Query('
DELETE
from ArtistAlternateNames
where ArtistId NOT IN
(SELECT DISTINCT ArtistId FROM Artworks)
');
}
} }

View file

@ -336,10 +336,9 @@ class Artwork extends PropertiesBase{
} }
/** /**
* @param array<mixed> $uploadedFile
* @throws \Exceptions\ValidationException * @throws \Exceptions\ValidationException
*/ */
protected function Validate(array &$uploadedFile = []): void{ protected function Validate(?string $imagePath = null, bool $isImageRequired = true): void{
$now = new DateTime('now', new DateTimeZone('UTC')); $now = new DateTime('now', new DateTimeZone('UTC'));
$thisYear = intval($now->format('Y')); $thisYear = intval($now->format('Y'));
$error = new Exceptions\ValidationException(); $error = new Exceptions\ValidationException();
@ -503,23 +502,17 @@ class Artwork extends PropertiesBase{
// No duplicates found, continue // No duplicates found, continue
} }
if($isImageRequired && $imagePath === null){
$error->Add(new Exceptions\InvalidImageUploadException('An image is required.'));
}
if($imagePath !== null && $this->MimeType !== null){
if(!is_writable(WEB_ROOT . COVER_ART_UPLOAD_PATH)){ if(!is_writable(WEB_ROOT . COVER_ART_UPLOAD_PATH)){
$error->Add(new Exceptions\InvalidImageUploadException('Upload path not writable.')); $error->Add(new Exceptions\InvalidImageUploadException('Upload path not writable.'));
} }
if(!empty($uploadedFile) && $this->MimeType !== null){
$uploadError = $uploadedFile['error'];
if($uploadError > UPLOAD_ERR_OK){
// see https://www.php.net/manual/en/features.file-upload.errors.php
$message = match($uploadError){
UPLOAD_ERR_INI_SIZE => 'Image upload too large (maximum ' . ini_get('upload_max_filesize') . ').',
default => 'Image failed to upload (error code ' . $uploadError . ').',
};
$error->Add(new Exceptions\InvalidImageUploadException($message));
}
// Check for minimum dimensions // Check for minimum dimensions
list($imageWidth, $imageHeight) = getimagesize($uploadedFile['tmp_name']); list($imageWidth, $imageHeight) = getimagesize($imagePath);
if(!$imageWidth || !$imageHeight || $imageWidth < ARTWORK_IMAGE_MINIMUM_WIDTH || $imageHeight < ARTWORK_IMAGE_MINIMUM_HEIGHT){ if(!$imageWidth || !$imageHeight || $imageWidth < ARTWORK_IMAGE_MINIMUM_WIDTH || $imageHeight < ARTWORK_IMAGE_MINIMUM_HEIGHT){
$error->Add(new Exceptions\ArtworkImageDimensionsTooSmallException()); $error->Add(new Exceptions\ArtworkImageDimensionsTooSmallException());
} }
@ -639,13 +632,13 @@ class Artwork extends PropertiesBase{
return $outputUrl; return $outputUrl;
} }
private function WriteImageAndThumbnails(string $imageUploadPath): void{ private function WriteImageAndThumbnails(string $imagePath): void{
exec('exiftool -quiet -overwrite_original -all= ' . escapeshellarg($imageUploadPath)); exec('exiftool -quiet -overwrite_original -all= ' . escapeshellarg($imagePath));
copy($imageUploadPath, $this->ImageFsPath); copy($imagePath, $this->ImageFsPath);
// Generate the thumbnails // Generate the thumbnails
try{ try{
$image = new Image($imageUploadPath); $image = new Image($imagePath);
$image->Resize($this->ThumbFsPath, ARTWORK_THUMBNAIL_WIDTH, ARTWORK_THUMBNAIL_HEIGHT); $image->Resize($this->ThumbFsPath, ARTWORK_THUMBNAIL_WIDTH, ARTWORK_THUMBNAIL_HEIGHT);
$image->Resize($this->Thumb2xFsPath, ARTWORK_THUMBNAIL_WIDTH * 2, ARTWORK_THUMBNAIL_HEIGHT * 2); $image->Resize($this->Thumb2xFsPath, ARTWORK_THUMBNAIL_WIDTH * 2, ARTWORK_THUMBNAIL_HEIGHT * 2);
} }
@ -655,14 +648,13 @@ class Artwork extends PropertiesBase{
} }
/** /**
* @param array<mixed> $uploadedFile
* @throws \Exceptions\ValidationException * @throws \Exceptions\ValidationException
* @throws \Exceptions\InvalidImageUploadException * @throws \Exceptions\InvalidImageUploadException
*/ */
public function Create(array $uploadedFile): void{ public function Create(?string $imagePath = null): void{
$this->MimeType = ImageMimeType::FromFile($uploadedFile['tmp_name'] ?? null); $this->MimeType = ImageMimeType::FromFile($imagePath);
$this->Validate($uploadedFile); $this->Validate($imagePath, true);
$this->Created = new DateTime(); $this->Created = new DateTime();
@ -713,18 +705,19 @@ class Artwork extends PropertiesBase{
', [$this->ArtworkId, $tag->TagId]); ', [$this->ArtworkId, $tag->TagId]);
} }
$this->WriteImageAndThumbnails($uploadedFile['tmp_name']); if($imagePath !== null){
$this->WriteImageAndThumbnails($imagePath);
}
} }
/** /**
* @param array<mixed> $uploadedFile
* @throws \Exceptions\ValidationException * @throws \Exceptions\ValidationException
*/ */
public function Save(array $uploadedFile = []): void{ public function Save(?string $imagePath = null): void{
$this->_UrlName = null; $this->_UrlName = null;
if(!empty($uploadedFile) && $uploadedFile['error'] == UPLOAD_ERR_OK){ if($imagePath !== null){
$this->MimeType = ImageMimeType::FromFile($uploadedFile['tmp_name'] ?? null); $this->MimeType = ImageMimeType::FromFile($imagePath);
// Manually set the updated timestamp, because if we only update the image and nothing else, the row's // Manually set the updated timestamp, because if we only update the image and nothing else, the row's
// updated timestamp won't change automatically. // updated timestamp won't change automatically.
@ -734,7 +727,7 @@ class Artwork extends PropertiesBase{
$this->_Thumb2xUrl = null; $this->_Thumb2xUrl = null;
} }
$this->Validate($uploadedFile); $this->Validate($imagePath, false);
$tags = []; $tags = [];
foreach($this->Tags as $artworkTag){ foreach($this->Tags as $artworkTag){
@ -781,8 +774,17 @@ class Artwork extends PropertiesBase{
$this->ArtworkId] $this->ArtworkId]
); );
Artist::DeleteUnreferencedArtists(); // Delete artists who are no longer to attached to an artwork
// Don't delete from the ArtistAlternateNames table to prevent accidentally
// deleting those manually-added entries.
Db::Query('
DELETE
from Artists
where ArtistId not in
(select distinct ArtistId from Artworks)
');
// Update tags for this artworke
Db::Query(' Db::Query('
DELETE from ArtworkTags DELETE from ArtworkTags
where where
@ -799,8 +801,8 @@ class Artwork extends PropertiesBase{
} }
// Handle the uploaded file if the user provided one during the save. // Handle the uploaded file if the user provided one during the save.
if(!empty($uploadedFile) && $uploadedFile['error'] == UPLOAD_ERR_OK){ if($imagePath !== null){
$this->WriteImageAndThumbnails($uploadedFile['tmp_name']); $this->WriteImageAndThumbnails($imagePath);
} }
} }

View file

@ -3,5 +3,11 @@
namespace Exceptions; namespace Exceptions;
class InvalidImageUploadException extends AppException{ class InvalidImageUploadException extends AppException{
protected $message = 'Uploaded image is invalid.'; public function __construct(?string $message = null){
if($message === null){
$message = 'Uploaded image is invalid.';
}
parent::__construct($message);
}
} }

View file

@ -187,8 +187,8 @@ class Library{
$artworks = Db::Query(' $artworks = Db::Query('
SELECT * SELECT *
from Artworks from Artworks
where Status = ? and EbookWwwFilesystemPath is not null where EbookWwwFilesystemPath is not null
', [ArtworkStatus::Approved->value], 'Artwork'); ', [], 'Artwork');
} }
elseif($status == 'all-submitter' && $submitterUserId !== null){ elseif($status == 'all-submitter' && $submitterUserId !== null){
$artworks = Db::Query(' $artworks = Db::Query('

View file

@ -36,12 +36,12 @@ try{
$artwork->ReviewerUserId = $GLOBALS['User']->UserId; $artwork->ReviewerUserId = $GLOBALS['User']->UserId;
} }
// Confirm that the files came from POST // Confirm that we have an image and that it came from POST
if(!is_uploaded_file($_FILES['artwork-image']['tmp_name'])){ if(isset($_FILES['artwork-image']) && (!is_uploaded_file($_FILES['artwork-image']['tmp_name']) || $_FILES['artwork-image']['error'] > UPLOAD_ERR_OK)){
throw new Exceptions\InvalidImageUploadException(); throw new Exceptions\InvalidImageUploadException();
} }
$artwork->Create($_FILES['artwork-image'] ?? []); $artwork->Create($_FILES['artwork-image']['tmp_name'] ?? null);
$_SESSION['artwork'] = $artwork; $_SESSION['artwork'] = $artwork;
$_SESSION['artwork-created'] = true; $_SESSION['artwork-created'] = true;
@ -75,18 +75,18 @@ try{
$artwork->Status = $newStatus; $artwork->Status = $newStatus;
} }
$uploadedFile = []; // Confirm that we have an image and that it came from POST
$uploadError = $_FILES['artwork-image']['error']; if(isset($_FILES['artwork-image'])){
if(!is_uploaded_file($_FILES['artwork-image']['tmp_name']) || $_FILES['artwork-image']['error'] > UPLOAD_ERR_OK){
if($uploadError == UPLOAD_ERR_OK){ throw new Exceptions\InvalidImageUploadException();
$uploadedFile = $_FILES['artwork-image']; }
} }
// No uploaded file as part of this edit, so retain the MimeType of the original submission.
else{ else{
// No uploaded file as part of this edit, so retain the MimeType of the original submission.
$artwork->MimeType = $originalArtwork->MimeType; $artwork->MimeType = $originalArtwork->MimeType;
} }
$artwork->Save($uploadedFile); $artwork->Save($_FILES['artwork-image']['tmp_name'] ?? null);
$_SESSION['artwork'] = $artwork; $_SESSION['artwork'] = $artwork;
$_SESSION['artwork-saved'] = true; $_SESSION['artwork-saved'] = true;
@ -110,7 +110,6 @@ try{
} }
$artwork->ReviewerUserId = $GLOBALS['User']->UserId; $artwork->ReviewerUserId = $GLOBALS['User']->UserId;
$artwork->Status = $newStatus;
} }
$newEbookWwwFilesystemPath = HttpInput::Str(POST, 'artwork-ebook-www-filesystem-path', false) ?? null; $newEbookWwwFilesystemPath = HttpInput::Str(POST, 'artwork-ebook-www-filesystem-path', false) ?? null;
@ -118,9 +117,8 @@ try{
throw new Exceptions\InvalidPermissionsException(); throw new Exceptions\InvalidPermissionsException();
} }
$artwork->ReviewerUserId = $GLOBALS['User']->UserId; $artwork->Status = $newStatus ?? $artwork->Status;
$artwork->Status = $newStatus; $artwork->EbookWwwFilesystemPath = $newEbookWwwFilesystemPath ?? $artwork->EbookWwwFilesystemPath;
$artwork->EbookWwwFilesystemPath = $newEbookWwwFilesystemPath;
$artwork->Save(); $artwork->Save();