Implement FilterEbooks via DB

This commit is contained in:
Mike Colagrosso 2024-07-05 18:45:12 -06:00 committed by Alex Cabal
parent d9b6e3020c
commit 989dcab9f0
2 changed files with 56 additions and 81 deletions

View file

@ -16,95 +16,68 @@ use function Safe\usort;
class Library{ class Library{
/** /**
* @param array<string> $tags * @param array<string> $tags
* @return array<Ebook> * @return array<string, array<Ebook>|int>
* @throws Exceptions\AppException
*/ */
public static function FilterEbooks(string $query = null, array $tags = [], EbookSortType $sort = null): array{ public static function FilterEbooks(string $query = null, array $tags = [], EbookSortType $sort = null, int $page = 1, int $perPage = EBOOKS_PER_PAGE): array{
$ebooks = Library::GetEbooks(); // Returns an array of:
$matches = $ebooks; // ['ebooks'] => array<Ebook>,
// ['ebooksCount'] => int
if($sort === null){ $limit = $perPage;
$sort = EbookSortType::Newest; $offset = (($page - 1) * $perPage);
$joinContributors = '';
$joinTags = '';
$params = [];
$whereCondition = 'where true';
$orderBy = 'e.EbookCreated desc';
if($sort == EbookSortType::AuthorAlpha){
$joinContributors = 'inner join Contributors con using (EbookId)';
$whereCondition .= ' AND con.MarcRole = "aut"';
$orderBy = 'con.SortName, e.EbookCreated desc';
}
elseif($sort == EbookSortType::ReadingEase){
$orderBy = 'e.ReadingEase desc';
}
elseif($sort == EbookSortType::Length){
$orderBy = 'e.WordCount';
} }
if(sizeof($tags) > 0 && !in_array('all', $tags)){ // 0 tags means "all ebooks" if(sizeof($tags) > 0 && !in_array('all', $tags)){ // 0 tags means "all ebooks"
$matches = []; $joinTags = 'inner join EbookTags et using (EbookId)
foreach($tags as $tag){ inner join Tags t using (TagId)';
foreach($ebooks as $ebook){ $whereCondition .= ' AND t.Name in ' . Db::CreateSetSql($tags) . ' ';
if($ebook->HasTag($tag)){ $params = $tags;
$matches[$ebook->Identifier] = $ebook;
}
}
}
} }
if($query !== null){ if($query !== null && $query != ''){
$filteredMatches = []; $query = trim(preg_replace('|[^a-zA-Z0-9 ]|ius', ' ', Formatter::RemoveDiacritics($query)));
$whereCondition .= ' AND match(e.IndexableText) against(?) ';
foreach($matches as $ebook){ $params[] = $query;
if($ebook->Contains($query)){
$filteredMatches[$ebook->Identifier] = $ebook;
}
}
$matches = $filteredMatches;
} }
switch($sort){ $ebooksCount = Db::QueryInt('
case EbookSortType::AuthorAlpha: SELECT count(distinct e.EbookId)
usort($matches, function($a, $b){ from Ebooks e
return strcmp(mb_strtolower($a->Authors[0]->SortName), mb_strtolower($b->Authors[0]->SortName)); ' . $joinContributors . '
}); ' . $joinTags . '
break; ' . $whereCondition . '
', $params);
case EbookSortType::Newest: $params[] = $limit;
usort($matches, function($a, $b){ $params[] = $offset;
if($a->EbookCreated < $b->EbookCreated){
return -1;
}
elseif($a->EbookCreated == $b->EbookCreated){
return 0;
}
else{
return 1;
}
});
$matches = array_reverse($matches); $ebooks = Db::Query('
break; SELECT distinct e.*
from Ebooks e
' . $joinContributors . '
' . $joinTags . '
' . $whereCondition . '
order by ' . $orderBy . '
limit ?
offset ?', $params, Ebook::class);
case EbookSortType::ReadingEase: return ['ebooks' => $ebooks, 'ebooksCount' => $ebooksCount];
usort($matches, function($a, $b){
if($a->ReadingEase < $b->ReadingEase){
return -1;
}
elseif($a->ReadingEase == $b->ReadingEase){
return 0;
}
else{
return 1;
}
});
$matches = array_reverse($matches);
break;
case EbookSortType::Length:
usort($matches, function($a, $b){
if($a->WordCount < $b->WordCount){
return -1;
}
elseif($a->WordCount == $b->WordCount){
return 0;
}
else{
return 1;
}
});
break;
}
return $matches;
} }
/** /**

View file

@ -35,12 +35,14 @@ try{
$tags = []; $tags = [];
} }
$ebooks = Library::FilterEbooks($query != '' ? $query : null, $tags, $sort); $result = Library::FilterEbooks($query != '' ? $query : null, $tags, $sort, $page, $perPage);
/** @var array<Ebook> $ebooks */
$ebooks = $result['ebooks'];
/** @var int $totalEbooks */
$totalEbooks = $result['ebooksCount'];
$pageTitle = 'Browse Standard Ebooks'; $pageTitle = 'Browse Standard Ebooks';
$pageHeader = 'Browse Ebooks'; $pageHeader = 'Browse Ebooks';
$pages = ceil(sizeof($ebooks) / $perPage); $pages = ceil($totalEbooks / $perPage);
$totalEbooks = sizeof($ebooks);
$ebooks = array_slice($ebooks, ($page - 1) * $perPage, $perPage);
if($page > 1){ if($page > 1){
$pageTitle .= ', page ' . $page; $pageTitle .= ', page ' . $page;