Convert some constants to enums

This commit is contained in:
Alex Cabal 2024-01-14 22:32:47 -06:00
parent 793d832e92
commit 531e3600ea
14 changed files with 93 additions and 248 deletions

View file

@ -134,12 +134,16 @@ Before submitting design contributions, please discuss them with the Standard Eb
- Finding a self-hosted replacement for GitHub, like possibly [Gitea](https://gitea.io/) or [GitLab](https://about.gitlab.com/), and figuring out how to reproducably install and update it on the SE server. - Finding a self-hosted replacement for GitHub, like possibly [Gitea](https://gitea.io/) or [GitLab](https://about.gitlab.com/), and figuring out how to reproducably install and update it on the SE server.
- Converting some constants to enums, like `SORT_*` or `SOURCE_*`.
### Artwork database ### Artwork database
- Allow submitter or admins to edit unapproved artwork submissions. Approved/in use submissions should not be editable by anyone. - Allow submitter or admins to edit unapproved artwork submissions. Approved/in use submissions should not be editable by anyone.
- Include in-use ebook slug as a search parameter when searching for artwork by keyword. - Include in-use ebook slug as a search parameter when searching for artwork by keyword.
- Remove `in_use` status for an artwork; instead, an artwork with an `EbookWwwFilesystemPath` that is not `null` should be considered to be "in use" regardless of its `Status`.
## PHP code style ## PHP code style
- Indent with tabs. - Indent with tabs.

View file

@ -64,7 +64,7 @@ class Artist extends PropertiesBase{
$error->Add(new Exceptions\ArtistNameRequiredException()); $error->Add(new Exceptions\ArtistNameRequiredException());
} }
if($this->Name !== null && strlen($this->Name) > COVER_ARTWORK_MAX_STRING_LENGTH){ if($this->Name !== null && strlen($this->Name) > ARTWORK_MAX_STRING_LENGTH){
$error->Add(new Exceptions\StringTooLongException('Artist Name')); $error->Add(new Exceptions\StringTooLongException('Artist Name'));
} }

View file

@ -20,6 +20,7 @@ use function Safe\preg_replace;
* @property string $ThumbUrl * @property string $ThumbUrl
* @property string $Thumb2xUrl * @property string $Thumb2xUrl
* @property string $Dimensions * @property string $Dimensions
* @property ArtworkStatus|string|null $Status
* @property Ebook $Ebook * @property Ebook $Ebook
* @property Museum $Museum * @property Museum $Museum
* @property User $Submitter * @property User $Submitter
@ -35,7 +36,6 @@ class Artwork extends PropertiesBase{
public bool $CompletedYearIsCirca = false; public bool $CompletedYearIsCirca = false;
public ?DateTime $Created = null; public ?DateTime $Created = null;
public ?DateTime $Updated = null; public ?DateTime $Updated = null;
public ?string $Status = null;
public ?string $EbookWwwFilesystemPath = null; public ?string $EbookWwwFilesystemPath = null;
public ?int $SubmitterUserId = null; public ?int $SubmitterUserId = null;
public ?int $ReviewerUserId = null; public ?int $ReviewerUserId = null;
@ -60,6 +60,7 @@ class Artwork extends PropertiesBase{
protected ?User $_Submitter = null; protected ?User $_Submitter = null;
protected ?User $_Reviewer = null; protected ?User $_Reviewer = null;
protected ?ImageMimeType $_MimeType = null; protected ?ImageMimeType $_MimeType = null;
protected ?ArtworkStatus $_Status = null;
// ******* // *******
// SETTERS // SETTERS
@ -68,7 +69,7 @@ class Artwork extends PropertiesBase{
/** /**
* @param string|null|array<ArtworkTag> $tags * @param string|null|array<ArtworkTag> $tags
*/ */
protected function SetTags(string|array|null $tags): void{ protected function SetTags(null|string|array $tags): void{
if($tags === null || is_array($tags)){ if($tags === null || is_array($tags)){
$this->_Tags = $tags; $this->_Tags = $tags;
} }
@ -85,6 +86,30 @@ class Artwork extends PropertiesBase{
} }
} }
protected function SetStatus(null|string|ArtworkStatus $status): void{
if($status instanceof ArtworkStatus){
$this->_Status = $status;
}
elseif($status === null){
$this->_Status = null;
}
else{
$this->_Status = ArtworkStatus::from($status);
}
}
protected function SetMimeType(null|string|ImageMimeType $mimeType): void{
if($mimeType instanceof ImageMimeType){
$this->_MimeType = $mimeType;
}
elseif($mimeType === null){
$this->_MimeType = null;
}
else{
$this->_MimeType = ImageMimeType::tryFrom($mimeType);
}
}
// ******* // *******
// GETTERS // GETTERS
// ******* // *******
@ -235,15 +260,6 @@ class Artwork extends PropertiesBase{
return $this->_Ebook; return $this->_Ebook;
} }
protected function SetMimeType(null|string|ImageMimeType $mimeType): void{
if(is_string($mimeType)){
$this->_MimeType = ImageMimeType::tryFrom($mimeType);
}
else{
$this->_MimeType = $mimeType;
}
}
// ******* // *******
// METHODS // METHODS
// ******* // *******
@ -277,7 +293,7 @@ class Artwork extends PropertiesBase{
$error->Add(new Exceptions\ArtworkNameRequiredException()); $error->Add(new Exceptions\ArtworkNameRequiredException());
} }
if($this->Name !== null && strlen($this->Name) > COVER_ARTWORK_MAX_STRING_LENGTH){ if($this->Name !== null && strlen($this->Name) > ARTWORK_MAX_STRING_LENGTH){
$error->Add(new Exceptions\StringTooLongException('Artwork Name')); $error->Add(new Exceptions\StringTooLongException('Artwork Name'));
} }
@ -293,33 +309,33 @@ class Artwork extends PropertiesBase{
$error->Add(new Exceptions\InvalidPublicationYearException()); $error->Add(new Exceptions\InvalidPublicationYearException());
} }
if($this->Status !== null && !in_array($this->Status, [COVER_ARTWORK_STATUS_UNVERIFIED, COVER_ARTWORK_STATUS_APPROVED, COVER_ARTWORK_STATUS_DECLINED, COVER_ARTWORK_STATUS_IN_USE])){ if($this->Status === null){
$error->Add(new Exceptions\InvalidArtworkException('Invalid status.')); $error->Add(new Exceptions\InvalidArtworkException('Invalid status.'));
} }
if($this->Status === COVER_ARTWORK_STATUS_IN_USE && $this->EbookWwwFilesystemPath === null){ if($this->Status == ArtworkStatus::InUse && $this->EbookWwwFilesystemPath === null){
$error->Add(new Exceptions\MissingEbookException()); $error->Add(new Exceptions\MissingEbookException());
} }
if(count($this->Tags) == 0){ if(count($this->Tags) == 0){
// In-use artwork doesn't have user-provided tags. // In-use artwork doesn't have user-provided tags.
if($this->Status !== COVER_ARTWORK_STATUS_IN_USE){ if($this->Status != ArtworkStatus::InUse){
$error->Add(new Exceptions\TagsRequiredException()); $error->Add(new Exceptions\TagsRequiredException());
} }
} }
if(count($this->Tags) > COVER_ARTWORK_MAX_TAGS){ if(count($this->Tags) > ARTWORK_MAX_TAGS){
$error->Add(new Exceptions\TooManyTagsException()); $error->Add(new Exceptions\TooManyTagsException());
} }
foreach($this->Tags as $tag){ foreach($this->Tags as $tag){
if(strlen($tag->Name) > COVER_ARTWORK_MAX_STRING_LENGTH){ if(strlen($tag->Name) > ARTWORK_MAX_STRING_LENGTH){
$error->Add(new Exceptions\StringTooLongException('Artwork Tag: '. $tag->Name)); $error->Add(new Exceptions\StringTooLongException('Artwork Tag: '. $tag->Name));
} }
} }
if($this->MuseumUrl !== null){ if($this->MuseumUrl !== null){
if(strlen($this->MuseumUrl) > COVER_ARTWORK_MAX_STRING_LENGTH){ if(strlen($this->MuseumUrl) > ARTWORK_MAX_STRING_LENGTH){
$error->Add(new Exceptions\StringTooLongException('Link to an approved museum page')); $error->Add(new Exceptions\StringTooLongException('Link to an approved museum page'));
} }
@ -333,7 +349,7 @@ class Artwork extends PropertiesBase{
} }
if($this->PublicationYearPageUrl !== null){ if($this->PublicationYearPageUrl !== null){
if(strlen($this->PublicationYearPageUrl) > COVER_ARTWORK_MAX_STRING_LENGTH){ if(strlen($this->PublicationYearPageUrl) > ARTWORK_MAX_STRING_LENGTH){
$error->Add(new Exceptions\StringTooLongException('Link to page with year of publication')); $error->Add(new Exceptions\StringTooLongException('Link to page with year of publication'));
} }
@ -351,7 +367,7 @@ class Artwork extends PropertiesBase{
} }
if($this->CopyrightPageUrl !== null){ if($this->CopyrightPageUrl !== null){
if(strlen($this->CopyrightPageUrl) > COVER_ARTWORK_MAX_STRING_LENGTH){ if(strlen($this->CopyrightPageUrl) > ARTWORK_MAX_STRING_LENGTH){
$error->Add(new Exceptions\StringTooLongException('Link to page with copyright details')); $error->Add(new Exceptions\StringTooLongException('Link to page with copyright details'));
} }
@ -369,7 +385,7 @@ class Artwork extends PropertiesBase{
} }
if($this->ArtworkPageUrl !== null){ if($this->ArtworkPageUrl !== null){
if(strlen($this->ArtworkPageUrl) > COVER_ARTWORK_MAX_STRING_LENGTH){ if(strlen($this->ArtworkPageUrl) > ARTWORK_MAX_STRING_LENGTH){
$error->Add(new Exceptions\StringTooLongException('Link to page with artwork')); $error->Add(new Exceptions\StringTooLongException('Link to page with artwork'));
} }
@ -437,7 +453,7 @@ class Artwork extends PropertiesBase{
// Check for minimum dimensions // Check for minimum dimensions
list($imageWidth, $imageHeight) = getimagesize($uploadedFile['tmp_name']); list($imageWidth, $imageHeight) = getimagesize($uploadedFile['tmp_name']);
if(!$imageWidth || !$imageHeight || $imageWidth < COVER_ARTWORK_IMAGE_MINIMUM_WIDTH || $imageHeight < COVER_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());
} }
} }
@ -624,8 +640,8 @@ class Artwork extends PropertiesBase{
// Generate the thumbnails // Generate the thumbnails
try{ try{
$image = new Image($imageUploadPath); $image = new Image($imageUploadPath);
$image->Resize(WEB_ROOT . $this->ThumbUrl, COVER_THUMBNAIL_WIDTH, COVER_THUMBNAIL_HEIGHT); $image->Resize(WEB_ROOT . $this->ThumbUrl, ARTWORK_THUMBNAIL_WIDTH, ARTWORK_THUMBNAIL_HEIGHT);
$image->Resize(WEB_ROOT . $this->Thumb2xUrl, COVER_THUMBNAIL_WIDTH * 2, COVER_THUMBNAIL_HEIGHT * 2); $image->Resize(WEB_ROOT . $this->Thumb2xUrl, ARTWORK_THUMBNAIL_WIDTH * 2, ARTWORK_THUMBNAIL_HEIGHT * 2);
} }
catch(\Safe\Exceptions\FilesystemException | \Safe\Exceptions\ImageException){ catch(\Safe\Exceptions\FilesystemException | \Safe\Exceptions\ImageException){
throw new Exceptions\InvalidImageUploadException('Failed to generate thumbnail.'); throw new Exceptions\InvalidImageUploadException('Failed to generate thumbnail.');
@ -669,12 +685,6 @@ class Artwork extends PropertiesBase{
); );
} }
public function MarkInUse(string $ebookWwwFilesystemPath): void{
$this->EbookWwwFilesystemPath = $ebookWwwFilesystemPath;
$this->Status = COVER_ARTWORK_STATUS_IN_USE;
$this->Save();
}
public function Delete(): void{ public function Delete(): void{
Db::Query(' Db::Query('
DELETE DELETE

7
lib/ArtworkStatus.php Normal file
View file

@ -0,0 +1,7 @@
<?
enum ArtworkStatus: string{
case Unverified = 'unverified';
case Declined = 'declined';
case Approved = 'approved';
case InUse = 'in_use';
}

View file

@ -38,17 +38,13 @@ const SORT_AUTHOR_ALPHA = 'author-alpha';
const SORT_READING_EASE = 'reading-ease'; const SORT_READING_EASE = 'reading-ease';
const SORT_LENGTH = 'length'; const SORT_LENGTH = 'length';
const COVER_THUMBNAIL_HEIGHT = 350; const ARTWORK_THUMBNAIL_HEIGHT = 350;
const COVER_THUMBNAIL_WIDTH = 350; const ARTWORK_THUMBNAIL_WIDTH = 350;
const COVER_ARTWORK_PER_PAGE = 20; const ARTWORK_PER_PAGE = 20;
const COVER_ARTWORK_STATUS_APPROVED = 'approved'; const ARTWORK_MAX_STRING_LENGTH = 250;
const COVER_ARTWORK_STATUS_DECLINED = 'declined'; const ARTWORK_MAX_TAGS = 15;
const COVER_ARTWORK_STATUS_IN_USE = 'in_use'; const ARTWORK_IMAGE_MINIMUM_WIDTH = 300;
const COVER_ARTWORK_STATUS_UNVERIFIED = 'unverified'; const ARTWORK_IMAGE_MINIMUM_HEIGHT = 300;
const COVER_ARTWORK_MAX_STRING_LENGTH = 250;
const COVER_ARTWORK_MAX_TAGS = 15;
const COVER_ARTWORK_IMAGE_MINIMUM_WIDTH = 300;
const COVER_ARTWORK_IMAGE_MINIMUM_HEIGHT = 300;
const SORT_COVER_ARTWORK_CREATED_NEWEST = 'created-newest'; const SORT_COVER_ARTWORK_CREATED_NEWEST = 'created-newest';
const SORT_COVER_ARTIST_ALPHA = 'artist-alpha'; const SORT_COVER_ARTIST_ALPHA = 'artist-alpha';
const SORT_COVER_ARTWORK_COMPLETED_NEWEST = 'completed-newest'; const SORT_COVER_ARTWORK_COMPLETED_NEWEST = 'completed-newest';

View file

@ -6,6 +6,6 @@ class ArtworkImageDimensionsTooSmallException extends AppException{
// This has to be initialized in a constructor because we use the number_format() function. // This has to be initialized in a constructor because we use the number_format() function.
public function __construct(){ public function __construct(){
$this->message = 'Image dimensions are too small. The minimum image size is ' . number_format(COVER_ARTWORK_IMAGE_MINIMUM_WIDTH) . ' × ' . number_format(COVER_ARTWORK_IMAGE_MINIMUM_HEIGHT) . '.'; $this->message = 'Image dimensions are too small. The minimum image size is ' . number_format(ARTWORK_IMAGE_MINIMUM_WIDTH) . ' × ' . number_format(ARTWORK_IMAGE_MINIMUM_HEIGHT) . '.';
} }
} }

View file

@ -2,5 +2,5 @@
namespace Exceptions; namespace Exceptions;
class TooManyTagsException extends AppException{ class TooManyTagsException extends AppException{
protected $message = 'Too many tags; the maximum is ' . COVER_ARTWORK_MAX_TAGS . '.'; protected $message = 'Too many tags; the maximum is ' . ARTWORK_MAX_TAGS . '.';
} }

View file

@ -1,172 +0,0 @@
#!/usr/bin/php
<?
require_once('/standardebooks.org/web/lib/Core.php');
$longopts = ['repoDir:', 'workDir:', 'ebookWwwFilesystemPath:', 'verbose'];
$options = getopt('v', $longopts);
$repoDir = $options['repoDir'] ?? false;
$workDir = $options['workDir'] ?? false;
$ebookWwwFilesystemPath = $options['ebookWwwFilesystemPath'] ?? false;
$verbose = false;
if(isset($options['v']) || isset($options['verbose'])){
$verbose = true;
}
/**
* Coverts SimpleXMLElement objects with inner tags like this:
* '<abbr>Mr.</abbr> Smith'
* to:
* 'Mr. Smith'
*/
function StripInnerTags($elements): ?string{
if($elements === false){
return null;
}
if(isset($elements[0])){
return strip_tags($elements[0]->asXML());
}
return null;
}
if(!$repoDir || !$workDir || !$ebookWwwFilesystemPath){
print("Expected usage: upsert-to-cover-art-database [-v] --repoDir <dir> --workDir <dir> --ebookWwwFilesystemPath <path>\n");
exit(1);
}
if($verbose){
print("\nrepoDir: $repoDir\n");
print("workDir: $workDir\n");
print("ebookWwwFilesystemPath: $ebookWwwFilesystemPath\n");
}
chdir($repoDir);
$contentOpf = shell_exec("git show HEAD:src/epub/content.opf");
$xml = new SimpleXMLElement(str_replace('xmlns=', 'ns=', $contentOpf));
$xml->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/');
$artistName = StripInnerTags($xml->xpath('/package/metadata/dc:contributor[@id="artist"]'));
if($artistName === null){
// Some ebooks have an artist-1 and artist-2. Take artist-1, which isn't ideal, but is usually correct.
$artistName = StripInnerTags($xml->xpath('/package/metadata/dc:contributor[@id="artist-1"]'));
if($artistName === null){
print($repoDir . " Error: Could not find artist name in content.opf\n");
exit($repoDir . " Error: missing artistName\n");
}
}
if(!file_exists($ebookWwwFilesystemPath . '/text/colophon.xhtml')){
exit($repoDir . ' Error: no text/colophon.xhtml at ' . $ebookWwwFilesystemPath . "\n");
}
$rawColophon = file_get_contents($ebookWwwFilesystemPath . '/text/colophon.xhtml');
if(empty($rawColophon)){
exit($repoDir . ' Error: empty colophon at ' . $ebookWwwFilesystemPath . "\n");
}
preg_match('|a painting completed \w+ (\d+)|ius', $rawColophon, $matches);
$completedYear = null;
if(sizeof($matches) == 2){
$completedYear = (int)$matches[1];
}
$colophonXml = new SimpleXMLElement(str_replace('xmlns=', 'ns=', $rawColophon));
$artworkName = StripInnerTags($colophonXml->xpath('/html/body/main/section/p/i[@epub:type="se:name.visual-art.painting"]'));
if($artworkName === null){
print($repoDir . " Error: Could not find artwork name in colophon.xhtml\n");
exit($repoDir . " Error: missing artworkName");
}
$artistUrlName = Formatter::MakeUrlSafe($artistName);
$artworkUrlName = Formatter::MakeUrlSafe($artworkName);
$artwork = null;
if($verbose){
print("artistName: $artistName\n");
print("artistUrlName: $artistUrlName\n");
print("completedYear: $completedYear\n");
print("artworkName: $artworkName\n");
print("artworkUrlName: $artworkUrlName\n");
}
try{
$artwork = Artwork::GetByUrlAndIsApproved($artistUrlName, $artworkUrlName);
}
catch(Exceptions\ArtworkNotFoundException){
// $artwork is null by default, just continue
}
if($artwork === null){
if($verbose){
printf($repoDir . " No existing artwork found at %s/%s, inserting new artwork.\n", $artistUrlName, $artworkUrlName);
}
// The ebook colophon provides the artist's name, but not their death year.
// Prefer matching an existing artist to creating a new record with a null death year if possible.
$artist = Artist::FindMatch($artistName);
if($artist === null){
$artist = new Artist();
$artist->Name = $artistName;
}
$artwork = new Artwork();
$artwork->Artist = new Artist();
$artwork->Artist = $artist;
$artwork->Name = $artworkName;
$artwork->CompletedYear = $completedYear;
$artwork->CompletedYearIsCirca = false;
$artwork->Created = new DateTime();
$artwork->Status = COVER_ARTWORK_STATUS_IN_USE;
$artwork->EbookWwwFilesystemPath = $ebookWwwFilesystemPath;
$artwork->MimeType = ImageMimeType::JPG;
$coverSourceFile = tempnam($workDir, 'cover.source.');
// Search for JPEG, PNG, and TIFF source files, in that order.
exec("git show HEAD:images/cover.source.jpg > $coverSourceFile.jpg", $shellOutput, $resultCode);
if($resultCode !== 0){
// No JPEG, try PNG.
exec("git show HEAD:images/cover.source.png > $coverSourceFile.png", $shellOutput, $resultCode);
if($resultCode == 0){
// Found PNG, convert it to JPEG.
exec("convert $coverSourceFile.png -resize '3750x>' -sampling-factor 4:2:0 -strip -quality 80 -colorspace RGB -interlace JPEG $coverSourceFile.jpg", $shellOutput, $resultCode);
if($resultCode !== 0){
exit($repoDir . " Error: Failed to convert images/cover.source.png to JPEG\n");
}
}else{
// No JPEG or PNG, try TIFF.
exec("git show HEAD:images/cover.source.tif > $coverSourceFile.tif", $shellOutput, $resultCode);
if($resultCode == 0){
// Found TIFF, convert it to JPEG.
exec("convert $coverSourceFile.tif -resize '3750x>' -sampling-factor 4:2:0 -strip -quality 80 -colorspace RGB -interlace JPEG $coverSourceFile.jpg", $shellOutput, $resultCode);
if($resultCode !== 0){
exit($repoDir . " Error: Failed to convert images/cover.source.tif to JPEG\n");
}
}else{
exit($repoDir . " Error: no images/cover.source.jpg or images/cover.source.png or images/cover.source.tif\n");
}
}
}
$uploadedFile = ['tmp_name' => $coverSourceFile . '.jpg', 'error' => UPLOAD_ERR_OK];
$artwork->Create($uploadedFile);
}
else{
if($verbose){
printf($repoDir . " Existing artwork found at %s/%s, updating its status.\n", $artistUrlName, $artworkUrlName);
}
if($artwork->CompletedYear != $completedYear){
printf($repoDir . " Error: Existing database artwork completed year, %d, does not match ebook colophon completed year, %d. Not updating database.\n", $artwork->CompletedYear, $completedYear);
exit($repoDir . " Error: completed year\n");
}
if($artwork->Status === COVER_ARTWORK_STATUS_IN_USE){
printf($repoDir . " Error: Existing database artwork already marked as 'in_use' by ebook '%s'. Not updating database.\n", $artwork->EbookWwwFilesystemPath);
exit($repoDir . " Error: in_use\n");
}
$artwork->MarkInUse($ebookWwwFilesystemPath);
}

View file

@ -3,7 +3,7 @@ $artworks = $artworks ?? [];
?> ?>
<ol class="artwork-list"> <ol class="artwork-list">
<? foreach($artworks as $artwork){ ?> <? foreach($artworks as $artwork){ ?>
<li <? if($artwork->Status == COVER_ARTWORK_STATUS_IN_USE){ ?> class="in-use"<? } ?>> <li <? if($artwork->Status == ArtworkStatus::InUse){ ?> class="in-use"<? } ?>>
<a href="<?= $artwork->Url ?>"> <a href="<?= $artwork->Url ?>">
<picture> <picture>
<source srcset="<?= $artwork->Thumb2xUrl ?> 2x, <?= $artwork->ThumbUrl ?> 1x" type="image/jpg"/> <source srcset="<?= $artwork->Thumb2xUrl ?> 2x, <?= $artwork->ThumbUrl ?> 1x" type="image/jpg"/>

View file

@ -2,8 +2,8 @@
$artwork = $artwork ?? null; $artwork = $artwork ?? null;
?> ?>
<? if($artwork !== null){ ?> <? if($artwork !== null){ ?>
<? if($artwork->Status === COVER_ARTWORK_STATUS_APPROVED){ ?>Approved<? } ?> <? if($artwork->Status == ArtworkStatus::Approved){ ?>Approved<? } ?>
<? if($artwork->Status === COVER_ARTWORK_STATUS_DECLINED){ ?>Declined<? } ?> <? if($artwork->Status == ArtworkStatus::Declined){ ?>Declined<? } ?>
<? if($artwork->Status === COVER_ARTWORK_STATUS_UNVERIFIED){ ?>Unverified<? } ?> <? if($artwork->Status == ArtworkStatus::Unverified){ ?>Unverified<? } ?>
<? if($artwork->Status === COVER_ARTWORK_STATUS_IN_USE){ ?>In use<? if($artwork->EbookWwwFilesystemPath !== null){ ?> for <? if($artwork->Ebook !== null && $artwork->Ebook->Url !== null){ ?><i><a href="<?= $artwork->Ebook->Url ?>"><?= Formatter::ToPlainText($artwork->Ebook->Title) ?></a></i><? }else{ ?><code><?= Formatter::ToPlainText($artwork->EbookWwwFilesystemPath) ?></code> (Unreleased)<? } ?><? } ?><? } ?> <? if($artwork->Status == ArtworkStatus::InUse){ ?>In use<? if($artwork->EbookWwwFilesystemPath !== null){ ?> for <? if($artwork->Ebook !== null && $artwork->Ebook->Url !== null){ ?><i><a href="<?= $artwork->Ebook->Url ?>"><?= Formatter::ToPlainText($artwork->Ebook->Title) ?></a></i><? }else{ ?><code><?= Formatter::ToPlainText($artwork->EbookWwwFilesystemPath) ?></code> (Unreleased)<? } ?><? } ?><? } ?>
<? } ?> <? } ?>

View file

@ -11,7 +11,7 @@ try{
$isAdminView = $GLOBALS['User']->Benefits->CanReviewArtwork ?? false; $isAdminView = $GLOBALS['User']->Benefits->CanReviewArtwork ?? false;
// If the artwork is not approved, and we're not an admin, don't show it. // If the artwork is not approved, and we're not an admin, don't show it.
if($artwork->Status != COVER_ARTWORK_STATUS_APPROVED && $artwork->Status != COVER_ARTWORK_STATUS_IN_USE && !$isAdminView){ if($artwork->Status != ArtworkStatus::Approved && $artwork->Status != ArtworkStatus::InUse && !$isAdminView){
throw new Exceptions\ArtworkNotFoundException(); throw new Exceptions\ArtworkNotFoundException();
} }
@ -138,10 +138,10 @@ catch(Exceptions\ArtworkNotFoundException){
<span>Artwork approval status</span> <span>Artwork approval status</span>
<span> <span>
<select name="artwork-status"> <select name="artwork-status">
<option value="<?= COVER_ARTWORK_STATUS_UNVERIFIED ?>"<? if($artwork->Status == COVER_ARTWORK_STATUS_UNVERIFIED){ ?> selected="selected"<? } ?>>Unverified</option> <option value="<?= ArtworkStatus::Unverified->value ?>"<? if($artwork->Status == ArtworkStatus::Unverified){ ?> selected="selected"<? } ?>>Unverified</option>
<option value="<?= COVER_ARTWORK_STATUS_DECLINED ?>"<? if($artwork->Status == COVER_ARTWORK_STATUS_DECLINED){ ?> selected="selected"<? } ?>>Declined</option> <option value="<?= ArtworkStatus::Declined->value ?>"<? if($artwork->Status == ArtworkStatus::Declined){ ?> selected="selected"<? } ?>>Declined</option>
<option value="<?= COVER_ARTWORK_STATUS_APPROVED ?>"<? if($artwork->Status == COVER_ARTWORK_STATUS_APPROVED){ ?> selected="selected"<? } ?>>Approved</option> <option value="<?= ArtworkStatus::Approved->value ?>"<? if($artwork->Status == ArtworkStatus::Approved){ ?> selected="selected"<? } ?>>Approved</option>
<option value="<?= COVER_ARTWORK_STATUS_IN_USE ?>"<? if($artwork->Status == COVER_ARTWORK_STATUS_IN_USE){ ?> selected="selected"<? } ?>>In use</option> <option value="<?= ArtworkStatus::InUse->value ?>"<? if($artwork->Status == ArtworkStatus::InUse){ ?> selected="selected"<? } ?>>In use</option>
</select> </select>
</span> </span>
</label> </label>

View file

@ -2,7 +2,7 @@
use function Safe\preg_replace; use function Safe\preg_replace;
$page = HttpInput::Int(GET, 'page') ?? 1; $page = HttpInput::Int(GET, 'page') ?? 1;
$perPage = HttpInput::Int(GET, 'per-page') ?? COVER_ARTWORK_PER_PAGE; $perPage = HttpInput::Int(GET, 'per-page') ?? ARTWORK_PER_PAGE;
$query = HttpInput::Str(GET, 'query', false) ?? ''; $query = HttpInput::Str(GET, 'query', false) ?? '';
$status = HttpInput::Str(GET, 'status', false) ?? null; $status = HttpInput::Str(GET, 'status', false) ?? null;
$sort = HttpInput::Str(GET, 'sort', false); $sort = HttpInput::Str(GET, 'sort', false);
@ -17,8 +17,8 @@ if($page <= 0){
$page = 1; $page = 1;
} }
if($perPage != COVER_ARTWORK_PER_PAGE && $perPage != 40 && $perPage != 80){ if($perPage != ARTWORK_PER_PAGE && $perPage != 40 && $perPage != 80){
$perPage = COVER_ARTWORK_PER_PAGE; $perPage = ARTWORK_PER_PAGE;
} }
// If we're passed string values that are the same as the defaults, // If we're passed string values that are the same as the defaults,
@ -37,8 +37,8 @@ if($status == 'all'){
} }
} }
if(!$isAdminView && $status !== 'all' && $status != COVER_ARTWORK_STATUS_APPROVED && $status != COVER_ARTWORK_STATUS_IN_USE){ if(!$isAdminView && $status !== 'all' && $status != ArtworkStatus::Approved->value && $status != ArtworkStatus::InUse->value){
$status = COVER_ARTWORK_STATUS_APPROVED; $status = ArtworkStatus::Approved->value;
} }
$artworks = Library::FilterArtwork($query != '' ? $query : null, $status, $sort); $artworks = Library::FilterArtwork($query != '' ? $query : null, $status, $sort);
@ -65,7 +65,7 @@ if($sort !== null){
$queryString .= '&amp;sort=' . urlencode($sort); $queryString .= '&amp;sort=' . urlencode($sort);
} }
if($perPage !== COVER_ARTWORK_PER_PAGE){ if($perPage !== ARTWORK_PER_PAGE){
$queryString .= '&amp;per-page=' . urlencode((string)$perPage); $queryString .= '&amp;per-page=' . urlencode((string)$perPage);
} }
@ -80,10 +80,10 @@ if($perPage !== COVER_ARTWORK_PER_PAGE){
<span> <span>
<select name="status" size="1"> <select name="status" size="1">
<option value="all"<? if($status === null){ ?> selected="selected"<? } ?>>All</option> <option value="all"<? if($status === null){ ?> selected="selected"<? } ?>>All</option>
<? if($isAdminView){ ?><option value="<?= COVER_ARTWORK_STATUS_UNVERIFIED ?>"<? if($status == COVER_ARTWORK_STATUS_UNVERIFIED){ ?> selected="selected"<? } ?>>Unverified</option><? } ?> <? if($isAdminView){ ?><option value="<?= ArtworkStatus::Unverified->value ?>"<? if($status == ArtworkStatus::Unverified->value){ ?> selected="selected"<? } ?>>Unverified</option><? } ?>
<? if($isAdminView){ ?><option value="<?= COVER_ARTWORK_STATUS_DECLINED ?>"<? if($status == COVER_ARTWORK_STATUS_DECLINED){ ?> selected="selected"<? } ?>>Declined</option><? } ?> <? if($isAdminView){ ?><option value="<?= ArtworkStatus::Declined->value ?>"<? if($status == ArtworkStatus::Declined->value){ ?> selected="selected"<? } ?>>Declined</option><? } ?>
<option value="<?= COVER_ARTWORK_STATUS_APPROVED ?>"<? if($status == COVER_ARTWORK_STATUS_APPROVED){ ?> selected="selected"<? } ?>>Approved</option> <option value="<?= ArtworkStatus::Approved->value ?>"<? if($status == ArtworkStatus::Approved->value){ ?> selected="selected"<? } ?>>Approved</option>
<option value="<?= COVER_ARTWORK_STATUS_IN_USE ?>"<? if($status == COVER_ARTWORK_STATUS_IN_USE){ ?> selected="selected"<? } ?>>In use</option> <option value="<?= ArtworkStatus::InUse->value ?>"<? if($status == ArtworkStatus::InUse->value){ ?> selected="selected"<? } ?>>In use</option>
</select> </select>
</span> </span>
</label> </label>

View file

@ -39,7 +39,7 @@ try{
$artwork->Artist = new Artist(); $artwork->Artist = new Artist();
if($GLOBALS['User']->Benefits->CanReviewOwnArtwork){ if($GLOBALS['User']->Benefits->CanReviewOwnArtwork){
$artwork->Status = COVER_ARTWORK_STATUS_APPROVED; $artwork->Status = ArtworkStatus::Approved;
} }
} }
} }
@ -140,7 +140,7 @@ catch(Exceptions\InvalidPermissionsException){
</label> </label>
<label> <label>
<span>High-resolution image</span> <span>High-resolution image</span>
<span>jpg, bmp, png, and tiff are accepted; <?= number_format(COVER_ARTWORK_IMAGE_MINIMUM_WIDTH) ?> × <?= number_format(COVER_ARTWORK_IMAGE_MINIMUM_HEIGHT) ?> minimum; 32MB max.</span> <span>jpg, bmp, png, and tiff are accepted; <?= number_format(ARTWORK_IMAGE_MINIMUM_WIDTH) ?> × <?= number_format(ARTWORK_IMAGE_MINIMUM_HEIGHT) ?> minimum; 32MB max.</span>
<input <input
type="file" type="file"
name="artwork-image" name="artwork-image"
@ -241,10 +241,10 @@ catch(Exceptions\InvalidPermissionsException){
<span>Artwork approval status</span> <span>Artwork approval status</span>
<span> <span>
<select name="artwork-status"> <select name="artwork-status">
<option value="<?= COVER_ARTWORK_STATUS_UNVERIFIED ?>"<? if($artwork->Status == COVER_ARTWORK_STATUS_UNVERIFIED){ ?> selected="selected"<? } ?>>Unverified</option> <option value="<?= ArtworkStatus::Unverified->value ?>"<? if($artwork->Status == ArtworkStatus::Unverified){ ?> selected="selected"<? } ?>>Unverified</option>
<option value="<?= COVER_ARTWORK_STATUS_DECLINED ?>"<? if($artwork->Status == COVER_ARTWORK_STATUS_DECLINED){ ?> selected="selected"<? } ?>>Declined</option> <option value="<?= ArtworkStatus::Declined->value ?>"<? if($artwork->Status == ArtworkStatus::Declined){ ?> selected="selected"<? } ?>>Declined</option>
<option value="<?= COVER_ARTWORK_STATUS_APPROVED ?>"<? if($artwork->Status == COVER_ARTWORK_STATUS_APPROVED){ ?> selected="selected"<? } ?>>Approved</option> <option value="<?= ArtworkStatus::Approved->value ?>"<? if($artwork->Status == ArtworkStatus::Approved){ ?> selected="selected"<? } ?>>Approved</option>
<option value="<?= COVER_ARTWORK_STATUS_IN_USE ?>"<? if($artwork->Status == COVER_ARTWORK_STATUS_IN_USE){ ?> selected="selected"<? } ?>>In use</option> <option value="<?= ArtworkStatus::InUse->value ?>"<? if($artwork->Status == ArtworkStatus::InUse){ ?> selected="selected"<? } ?>>In use</option>
</select> </select>
</span> </span>
</label> </label>

View file

@ -31,7 +31,7 @@ try{
$artwork->CompletedYear = HttpInput::Int(POST, 'artwork-year'); $artwork->CompletedYear = HttpInput::Int(POST, 'artwork-year');
$artwork->CompletedYearIsCirca = HttpInput::Bool(POST, 'artwork-year-is-circa', false) ?? false; $artwork->CompletedYearIsCirca = HttpInput::Bool(POST, 'artwork-year-is-circa', false) ?? false;
$artwork->Tags = HttpInput::Str(POST, 'artwork-tags', false) ?? []; $artwork->Tags = HttpInput::Str(POST, 'artwork-tags', false) ?? [];
$artwork->Status = HttpInput::Str(POST, 'artwork-status', false, COVER_ARTWORK_STATUS_UNVERIFIED); $artwork->Status = HttpInput::Str(POST, 'artwork-status', false);
$artwork->EbookWwwFilesystemPath = HttpInput::Str(POST, 'artwork-ebook-www-filesystem-path', false); $artwork->EbookWwwFilesystemPath = HttpInput::Str(POST, 'artwork-ebook-www-filesystem-path', false);
$artwork->SubmitterUserId = $GLOBALS['User']->UserId ?? null; $artwork->SubmitterUserId = $GLOBALS['User']->UserId ?? null;
$artwork->IsPublishedInUs = HttpInput::Bool(POST, 'artwork-is-published-in-us', false); $artwork->IsPublishedInUs = HttpInput::Bool(POST, 'artwork-is-published-in-us', false);
@ -45,12 +45,12 @@ try{
// Only approved reviewers can set the status to anything but unverified when uploading // Only approved reviewers can set the status to anything but unverified when uploading
// The submitter cannot review their own submissions unless they have special permission // The submitter cannot review their own submissions unless they have special permission
if($artwork->Status != COVER_ARTWORK_STATUS_UNVERIFIED && !$GLOBALS['User']->Benefits->CanReviewOwnArtwork){ if($artwork->Status !== ArtworkStatus::Unverified && !$GLOBALS['User']->Benefits->CanReviewOwnArtwork){
throw new Exceptions\InvalidPermissionsException(); throw new Exceptions\InvalidPermissionsException();
} }
// If the artwork is approved, set the reviewer // If the artwork is approved, set the reviewer
if($artwork->Status != COVER_ARTWORK_STATUS_UNVERIFIED){ if($artwork->Status !== ArtworkStatus::Unverified){
$artwork->ReviewerUserId = $GLOBALS['User']->UserId; $artwork->ReviewerUserId = $GLOBALS['User']->UserId;
} }
@ -95,11 +95,11 @@ try{
$artwork->ReviewerUserId = $GLOBALS['User']->UserId; $artwork->ReviewerUserId = $GLOBALS['User']->UserId;
$newStatus = HttpInput::Str(POST, 'artwork-status', false); $newStatus = ArtworkStatus::tryFrom(HttpInput::Str(POST, 'artwork-status', false) ?? '');
if($newStatus !== null){ if($newStatus !== null){
if($artwork->Status != $newStatus){ if($artwork->Status != $newStatus){
// Is the user attempting to review their own artwork? // Is the user attempting to review their own artwork?
if($artwork->Status != COVER_ARTWORK_STATUS_UNVERIFIED && $GLOBALS['User']->UserId == $artwork->SubmitterUserId && !$GLOBALS['User']->Benefits->CanReviewOwnArtwork){ if($artwork->Status != ArtworkStatus::Unverified && $GLOBALS['User']->UserId == $artwork->SubmitterUserId && !$GLOBALS['User']->Benefits->CanReviewOwnArtwork){
throw new Exceptions\InvalidPermissionsException(); throw new Exceptions\InvalidPermissionsException();
} }
} }