Convert artwork filters to enums

This commit is contained in:
Alex Cabal 2024-11-15 23:11:01 -06:00
parent 8546039b97
commit 05ac7884e9
4 changed files with 104 additions and 69 deletions

View file

@ -930,29 +930,29 @@ class Artwork{
* *
* @throws Exceptions\ArtistNotFoundException * @throws Exceptions\ArtistNotFoundException
*/ */
public static function GetAllByArtist(?string $artistUrlName, ?string $status, ?int $submitterUserId): array{ public static function GetAllByArtist(?string $artistUrlName, ?Enums\ArtworkFilterType $artworkFilterType, ?int $submitterUserId): array{
if($artistUrlName === null){ if($artistUrlName === null){
throw new Exceptions\ArtistNotFoundException(); throw new Exceptions\ArtistNotFoundException();
} }
// $status is only one of three special statuses, which are a subset of FilterArtwork() above: if($artworkFilterType === null){
// null: same as "all" $artworkFilterType = Enums\ArtworkFilterType::Approved;
// "all": Show all approved and in use artwork }
// "all-admin": Show all artwork regardless of status
// "all-submitter": Show all approved and in use artwork, plus unverified artwork from the submitter
$statusCondition = ''; $statusCondition = '';
$params = []; $params = [];
if($status == 'all-admin'){ if($artworkFilterType == Enums\ArtworkFilterType::Admin){
$statusCondition = 'true'; $statusCondition = 'true';
} }
elseif($status == 'all-submitter' && $submitterUserId !== null){ elseif($artworkFilterType == Enums\ArtworkFilterType::ApprovedSubmitter && $submitterUserId !== null){
$statusCondition = '(Status = ? or (Status = ? and SubmitterUserId = ?))'; $statusCondition = '(Status = ? or (Status = ? and SubmitterUserId = ?))';
$params[] = Enums\ArtworkStatusType::Approved->value; $params[] = Enums\ArtworkStatusType::Approved->value;
$params[] = Enums\ArtworkStatusType::Unverified->value; $params[] = Enums\ArtworkStatusType::Unverified->value;
$params[] = $submitterUserId; $params[] = $submitterUserId;
} }
else{ else{
// Default to the `Enums\ArtworkFilterType::Approved` view.
$statusCondition = 'Status = ?'; $statusCondition = 'Status = ?';
$params[] = Enums\ArtworkStatusType::Approved->value; $params[] = Enums\ArtworkStatusType::Approved->value;
} }
@ -973,47 +973,48 @@ class Artwork{
/** /**
* @return array{artworks: array<Artwork>, artworksCount: int} * @return array{artworks: array<Artwork>, artworksCount: int}
*/ */
public static function GetAllByFilter(?string $query = null, ?string $status = null, ?Enums\ArtworkSortType $sort = null, ?int $submitterUserId = null, int $page = 1, int $perPage = ARTWORK_PER_PAGE): array{ public static function GetAllByFilter(?string $query = null, ?Enums\ArtworkFilterType $artworkFilterType = null, ?Enums\ArtworkSortType $sort = null, ?int $submitterUserId = null, int $page = 1, int $perPage = ARTWORK_PER_PAGE): array{
// $status is either the string value of an ArtworkStatus enum, or one of these special statuses: if($artworkFilterType === null){
// null: same as "all" $artworkFilterType = Enums\ArtworkFilterType::Approved;
// "all": Show all approved and in use artwork }
// "all-admin": Show all artwork regardless of status
// "all-submitter": Show all approved and in use artwork, plus unverified artwork from the submitter
// "unverified-submitter": Show unverified artwork from the submitter
// "in-use": Show only in-use artwork
$statusCondition = ''; $statusCondition = '';
$params = []; $params = [];
if($status === null || $status == 'all'){ if($artworkFilterType == Enums\ArtworkFilterType::Admin){
$statusCondition = 'Status = ?';
$params[] = Enums\ArtworkStatusType::Approved->value;
}
elseif($status == 'all-admin'){
$statusCondition = 'true'; $statusCondition = 'true';
} }
elseif($status == 'all-submitter' && $submitterUserId !== null){ elseif($artworkFilterType == Enums\ArtworkFilterType::ApprovedSubmitter && $submitterUserId !== null){
$statusCondition = '(Status = ? or (Status = ? and SubmitterUserId = ?))'; $statusCondition = '(Status = ? or (Status = ? and SubmitterUserId = ?))';
$params[] = Enums\ArtworkStatusType::Approved->value; $params[] = Enums\ArtworkStatusType::Approved->value;
$params[] = Enums\ArtworkStatusType::Unverified->value; $params[] = Enums\ArtworkStatusType::Unverified->value;
$params[] = $submitterUserId; $params[] = $submitterUserId;
} }
elseif($status == 'unverified-submitter' && $submitterUserId !== null){ elseif($artworkFilterType == Enums\ArtworkFilterType::UnverifiedSubmitter && $submitterUserId !== null){
$statusCondition = 'Status = ? and SubmitterUserId = ?'; $statusCondition = 'Status = ? and SubmitterUserId = ?';
$params[] = Enums\ArtworkStatusType::Unverified->value; $params[] = Enums\ArtworkStatusType::Unverified->value;
$params[] = $submitterUserId; $params[] = $submitterUserId;
} }
elseif($status == 'in-use'){ elseif($artworkFilterType == Enums\ArtworkFilterType::ApprovedInUse){
$statusCondition = 'Status = ? and EbookUrl is not null'; $statusCondition = 'Status = ? and EbookUrl is not null';
$params[] = Enums\ArtworkStatusType::Approved->value; $params[] = Enums\ArtworkStatusType::Approved->value;
} }
elseif($status == Enums\ArtworkStatusType::Approved->value){ elseif($artworkFilterType == Enums\ArtworkFilterType::ApprovedNotInUse){
$statusCondition = 'Status = ? and EbookUrl is null'; $statusCondition = 'Status = ? and EbookUrl is null';
$params[] = Enums\ArtworkStatusType::Approved->value; $params[] = Enums\ArtworkStatusType::Approved->value;
} }
else{ elseif($artworkFilterType == Enums\ArtworkFilterType::Declined){
$statusCondition = 'Status = ?'; $statusCondition = 'Status = ?';
$params[] = $status; $params[] = Enums\ArtworkStatusType::Declined->value;
}
elseif($artworkFilterType == Enums\ArtworkFilterType::Unverified){
$statusCondition = 'Status = ?';
$params[] = Enums\ArtworkStatusType::Unverified->value;
}
else{
// Default to the `Enums\ArtworkFilterType::Approved` view.
$statusCondition = 'Status = ?';
$params[] = Enums\ArtworkStatusType::Approved->value;
} }
$orderBy = 'art.Created desc'; $orderBy = 'art.Created desc';
@ -1024,7 +1025,7 @@ class Artwork{
$orderBy = 'art.CompletedYear desc'; $orderBy = 'art.CompletedYear desc';
} }
// Remove diacritics and non-alphanumeric characters, but preserve apostrophes // Remove diacritics and non-alphanumeric characters, but preserve apostrophes.
if($query !== null && $query != ''){ if($query !== null && $query != ''){
$query = trim(preg_replace('|[^a-zA-Z0-9\' ]|ius', ' ', Formatter::RemoveDiacritics($query))); $query = trim(preg_replace('|[^a-zA-Z0-9\' ]|ius', ' ', Formatter::RemoveDiacritics($query)));
} }
@ -1032,9 +1033,7 @@ class Artwork{
$query = ''; $query = '';
} }
// We use replace() below because if there's multiple contributors separated by an underscore, // We use `replace()` below because if there's multiple contributors separated by an underscore, the underscore won't count as word boundary and we won't get a match. See <https://github.com/standardebooks/web/pull/325>.
// the underscore won't count as word boundary and we won't get a match.
// See https://github.com/standardebooks/web/pull/325
$limit = $perPage; $limit = $perPage;
$offset = (($page - 1) * $perPage); $offset = (($page - 1) * $perPage);
@ -1060,7 +1059,7 @@ class Artwork{
// Split the query on word boundaries followed by spaces. This keeps words with apostrophes intact. // Split the query on word boundaries followed by spaces. This keeps words with apostrophes intact.
$tokenArray = preg_split('/\b\s+/', $query, -1, PREG_SPLIT_NO_EMPTY); $tokenArray = preg_split('/\b\s+/', $query, -1, PREG_SPLIT_NO_EMPTY);
// Join the tokens with '|' to search on any token, but add word boundaries to force the full token to match // Join the tokens with `|` to search on any token, but add word boundaries to force the full token to match.
$tokenizedQuery = '\b(' . implode('|', $tokenArray) . ')\b'; $tokenizedQuery = '\b(' . implode('|', $tokenArray) . ')\b';
$params[] = $tokenizedQuery; // art.Name $params[] = $tokenizedQuery; // art.Name

View file

@ -0,0 +1,14 @@
<?
namespace Enums;
enum ArtworkFilterType: string{
case Admin = 'admin'; // Show all artwork, regardless of status.
case All = 'all'; // Show all artwork, but only approved artwork if the logged-in user is not an admin.
case Approved = 'approved'; // Show all approved artwork.
case ApprovedInUse = 'approved_in_use'; // Show all approved that is in-use.
case ApprovedNotInUse = 'approved_not_in_use'; // Show all approved that is not in-use.
case ApprovedSubmitter = 'approved_submitter'; // Show all approved artwork, plus unverified artwork which the logged-in user has submitted.
case Declined = 'declined'; // Show only declined artwork.
case Unverified = 'unverified'; // Show only unverified artwork.
case UnverifiedSubmitter = 'unverified_submitter'; // Show only unverified artwork that the logged-in user has submitted.
}

View file

@ -3,18 +3,18 @@ $isReviewerView = Session::$User?->Benefits?->CanReviewArtwork ?? false;
$submitterUserId = Session::$User?->Benefits?->CanUploadArtwork ? Session::$User->UserId : null; $submitterUserId = Session::$User?->Benefits?->CanUploadArtwork ? Session::$User->UserId : null;
$isSubmitterView = !$isReviewerView && $submitterUserId !== null; $isSubmitterView = !$isReviewerView && $submitterUserId !== null;
$filterArtworkStatus = 'all'; $artworkFilterType = Enums\ArtworkFilterType::Approved;
if($isReviewerView){ if($isReviewerView){
$filterArtworkStatus = 'all-admin'; $artworkFilterType = Enums\ArtworkFilterType::Admin;
} }
if($isSubmitterView){ if($isSubmitterView){
$filterArtworkStatus = 'all-submitter'; $artworkFilterType = Enums\ArtworkFilterType::ApprovedSubmitter;
} }
try{ try{
$artworks = Artwork::GetAllByArtist(HttpInput::Str(GET, 'artist-url-name'), $filterArtworkStatus, $submitterUserId); $artworks = Artwork::GetAllByArtist(HttpInput::Str(GET, 'artist-url-name'), $artworkFilterType, $submitterUserId);
if(sizeof($artworks) == 0){ if(sizeof($artworks) == 0){
throw new Exceptions\ArtistNotFoundException(); throw new Exceptions\ArtistNotFoundException();

View file

@ -1,10 +1,10 @@
<? <?
$artworks = [];
$page = HttpInput::Int(GET, 'page') ?? 1; $page = HttpInput::Int(GET, 'page') ?? 1;
$perPage = HttpInput::Int(GET, 'per-page') ?? ARTWORK_PER_PAGE; $perPage = HttpInput::Int(GET, 'per-page') ?? ARTWORK_PER_PAGE;
$query = HttpInput::Str(GET, 'query'); $query = HttpInput::Str(GET, 'query');
$queryEbookUrl = HttpInput::Str(GET, 'query-ebook-url'); $queryEbookUrl = HttpInput::Str(GET, 'query-ebook-url');
$status = HttpInput::Str(GET, 'status'); $artworkFilterType = Enums\ArtworkFilterType::tryFrom(HttpInput::Str(GET, 'status') ?? '');
$filterArtworkStatus = $status;
$sort = Enums\ArtworkSortType::tryFrom(HttpInput::Str(GET, 'sort') ?? ''); $sort = Enums\ArtworkSortType::tryFrom(HttpInput::Str(GET, 'sort') ?? '');
$pages = 0; $pages = 0;
$totalArtworkCount = 0; $totalArtworkCount = 0;
@ -30,43 +30,48 @@ try{
} }
if($isReviewerView){ if($isReviewerView){
if($status == 'all' || $status === null){ if($artworkFilterType == Enums\ArtworkFilterType::All || $artworkFilterType === null){
$filterArtworkStatus = 'all-admin'; $artworkFilterType = Enums\ArtworkFilterType::Admin;
}
if($artworkFilterType == Enums\ArtworkFilterType::UnverifiedSubmitter){
$artworkFilterType = Enums\ArtworkFilterType::Unverified;
} }
} }
if($isSubmitterView){ if($isSubmitterView){
if($status == 'all' || $status === null){ if($artworkFilterType == Enums\ArtworkFilterType::All || $artworkFilterType === null){
$filterArtworkStatus = 'all-submitter'; $artworkFilterType = Enums\ArtworkFilterType::ApprovedSubmitter;
} }
if($status == 'unverified'){ if($artworkFilterType == Enums\ArtworkFilterType::Unverified){
$filterArtworkStatus = 'unverified-submitter'; $artworkFilterType = Enums\ArtworkFilterType::UnverifiedSubmitter;
} }
} }
if(!$isReviewerView && !$isSubmitterView && !in_array($status, array('all', Enums\ArtworkStatusType::Approved->value, 'in-use'))){ if(
$status = Enums\ArtworkStatusType::Approved->value; !$isReviewerView
$filterArtworkStatus = $status; &&
!$isSubmitterView
&&
!in_array($artworkFilterType, [Enums\ArtworkFilterType::Approved, Enums\ArtworkFilterType::ApprovedNotInUse, Enums\ArtworkFilterType::ApprovedInUse])
){
$artworkFilterType = Enums\ArtworkFilterType::Approved;
} }
if($isReviewerView && !in_array($status, array('all', Enums\ArtworkStatusType::Unverified->value, Enums\ArtworkStatusType::Declined->value, Enums\ArtworkStatusType::Approved->value, 'in-use')) if(
&& !in_array($filterArtworkStatus, array('all-admin', Enums\ArtworkStatusType::Unverified->value, Enums\ArtworkStatusType::Declined->value, Enums\ArtworkStatusType::Approved->value, 'in-use'))){ $isSubmitterView
$status = Enums\ArtworkStatusType::Approved->value; &&
$filterArtworkStatus = $status; !in_array($artworkFilterType, [Enums\ArtworkFilterType::ApprovedSubmitter, Enums\ArtworkFilterType::UnverifiedSubmitter, Enums\ArtworkFilterType::ApprovedInUse, Enums\ArtworkFilterType::ApprovedNotInUse])
} ){
$artworkFilterType = Enums\ArtworkFilterType::ApprovedSubmitter;
if($isSubmitterView && !in_array($status, array('all', Enums\ArtworkStatusType::Unverified->value, Enums\ArtworkStatusType::Approved->value, 'in-use'))
&& !in_array($filterArtworkStatus, array('all-submitter', 'unverified-submitter', Enums\ArtworkStatusType::Approved->value, 'in-use'))){
$status = Enums\ArtworkStatusType::Approved->value;
$filterArtworkStatus = $status;
} }
if($queryEbookUrl !== null){ if($queryEbookUrl !== null){
$artworks = Db::Query('SELECT * from Artworks where EbookUrl = ? and Status = ? limit 1', [$queryEbookUrl, Enums\ArtworkStatusType::Approved], Artwork::class); // We're being called from the `review` script, and we're only interested if the artwork exists for this URL.
$totalArtworkCount = sizeof($artworks); $artworks[] = Db::Query('SELECT * from Artworks where EbookUrl = ? and Status = ? limit 1', [$queryEbookUrl, Enums\ArtworkStatusType::Approved], Artwork::class)[0] ?? throw new Exceptions\ArtworkNotFoundException();
$totalArtworkCount = 1;
} }
else{ else{
$result = Artwork::GetAllByFilter($query, $filterArtworkStatus, $sort, $submitterUserId, $page, $perPage); $result = Artwork::GetAllByFilter($query, $artworkFilterType, $sort, $submitterUserId, $page, $perPage);
$artworks = $result['artworks']; $artworks = $result['artworks'];
$totalArtworkCount = $result['artworksCount']; $totalArtworkCount = $result['artworksCount'];
} }
@ -84,8 +89,8 @@ try{
$queryStringParams['query'] = $query; $queryStringParams['query'] = $query;
} }
if($status !== null){ if($artworkFilterType !== null){
$queryStringParams['status'] = $status; $queryStringParams['status'] = $artworkFilterType->value;
} }
if($sort !== null){ if($sort !== null){
@ -118,6 +123,9 @@ try{
throw new Exceptions\PageOutOfBoundsException(); throw new Exceptions\PageOutOfBoundsException();
} }
} }
catch(Exceptions\ArtworkNotFoundException){
Template::Emit404();
}
catch(Exceptions\PageOutOfBoundsException){ catch(Exceptions\PageOutOfBoundsException){
$url = '/artworks?page=' . $pages; $url = '/artworks?page=' . $pages;
if($queryStringWithoutPage != ''){ if($queryStringWithoutPage != ''){
@ -131,21 +139,35 @@ catch(Exceptions\PageOutOfBoundsException){
<main class="artworks"> <main class="artworks">
<section class="narrow"> <section class="narrow">
<h1>Browse U.S. Public Domain Artwork</h1> <h1>Browse U.S. Public Domain Artwork</h1>
<p><? if(Session::$User?->Benefits->CanUploadArtwork){ ?><a href="/artworks/new">Submit new public domain artwork.</a><? }else{ ?>You can help Standard Ebooks by <a href="/artworks/new">submitting new public domain artwork</a> to add to this catalog for use in future ebooks. For free access to the submission form, <a href="/about#editor-in-chief">contact the Editor-in-Chief</a>.<? } ?></p> <p>
<? if(Session::$User?->Benefits->CanUploadArtwork){ ?>
<a href="/artworks/new">Submit new public domain artwork.</a>
<? }else{ ?>
You can help Standard Ebooks by <a href="/artworks/new">submitting new public domain artwork</a> to add to this catalog for use in future ebooks. For free access to the submission form, <a href="/about#editor-in-chief">contact the Editor-in-Chief</a>.
<? } ?>
</p>
<form class="browse-artwork" action="/artworks" method="get" rel="search"> <form class="browse-artwork" action="/artworks" method="get" rel="search">
<label> <label>
<span>Status</span> <span>Status</span>
<span> <span>
<select name="status" size="1"> <select name="status" size="1">
<option value="all"<? if($status === null){ ?> selected="selected"<? } ?>>All</option> <option value="<?= Enums\ArtworkFilterType::All->value ?>"<? if($artworkFilterType === null || $artworkFilterType == Enums\ArtworkFilterType::All){ ?> selected="selected"<? } ?>>All</option>
<? if($isReviewerView || $isSubmitterView){ ?><option value="<?= Enums\ArtworkStatusType::Unverified->value ?>"<? if($status == Enums\ArtworkStatusType::Unverified->value){ ?> selected="selected"<? } ?>>Unverified</option><? } ?> <? if($isReviewerView){ ?>
<? if($isReviewerView){ ?><option value="<?= Enums\ArtworkStatusType::Declined->value ?>"<? if($status == Enums\ArtworkStatusType::Declined->value){ ?> selected="selected"<? } ?>>Declined</option><? } ?> <option value="<?= Enums\ArtworkFilterType::Unverified->value ?>"<? if($artworkFilterType == Enums\ArtworkFilterType::Unverified){ ?> selected="selected"<? } ?>>Unverified</option>
<option value="<?= Enums\ArtworkStatusType::Approved->value ?>"<? if($status == Enums\ArtworkStatusType::Approved->value){ ?> selected="selected"<? } ?>>Approved, not in use</option> <? } ?>
<option value="in-use"<? if($status == 'in-use'){ ?> selected="selected"<? } ?>>In use</option> <? if($isSubmitterView){ ?>
<option value="<?= Enums\ArtworkFilterType::UnverifiedSubmitter->value ?>"<? if($artworkFilterType == Enums\ArtworkFilterType::UnverifiedSubmitter){ ?> selected="selected"<? } ?>>Unverified</option>
<? } ?>
<? if($isReviewerView){ ?>
<option value="<?= Enums\ArtworkFilterType::Declined->value ?>"<? if($artworkFilterType == Enums\ArtworkFilterType::Declined){ ?> selected="selected"<? } ?>>Declined</option>
<? } ?>
<option value="<?= Enums\ArtworkFilterType::ApprovedNotInUse->value ?>"<? if($artworkFilterType == Enums\ArtworkFilterType::ApprovedNotInUse){ ?> selected="selected"<? } ?>>Approved, not in use</option>
<option value="<?= Enums\ArtworkFilterType::ApprovedInUse->value ?>"<? if($artworkFilterType == Enums\ArtworkFilterType::ApprovedInUse){ ?> selected="selected"<? } ?>>Approved, in use</option>
</select> </select>
</span> </span>
</label> </label>
<label>Keywords <label>
<span>Keywords</span>
<input type="search" name="query" value="<?= Formatter::EscapeHtml($query) ?>"/> <input type="search" name="query" value="<?= Formatter::EscapeHtml($query) ?>"/>
</label> </label>
<label class="sort"> <label class="sort">