mirror of
https://github.com/standardebooks/web.git
synced 2025-07-12 01:22:23 -04:00
Refactor functions out of Library
This commit is contained in:
parent
1449148989
commit
b7b63a4be5
24 changed files with 419 additions and 444 deletions
|
@ -126,6 +126,16 @@ class Artist{
|
|||
', [$artistId], Artist::class)[0] ?? throw new Exceptions\ArtistNotFoundException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Artist>
|
||||
*/
|
||||
public static function GetAll(): array{
|
||||
return Db::Query('
|
||||
SELECT *
|
||||
from Artists
|
||||
order by Name asc', [], Artist::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exceptions\ArtistNotFoundException
|
||||
*/
|
||||
|
|
204
lib/Artwork.php
204
lib/Artwork.php
|
@ -7,6 +7,7 @@ use function Safe\getimagesize;
|
|||
use function Safe\parse_url;
|
||||
use function Safe\preg_match;
|
||||
use function Safe\preg_replace;
|
||||
use function Safe\preg_split;
|
||||
use function Safe\unlink;
|
||||
|
||||
/**
|
||||
|
@ -922,25 +923,194 @@ class Artwork{
|
|||
return $result[0] ?? throw new Exceptions\ArtworkNotFoundException();
|
||||
}
|
||||
|
||||
public static function FromHttpPost(): Artwork{
|
||||
$artwork = new Artwork();
|
||||
/**
|
||||
* @return array<Artwork>
|
||||
*
|
||||
* @throws Exceptions\ArtistNotFoundException
|
||||
*/
|
||||
public static function GetAllByArtist(?string $artistUrlName, ?string $status, ?int $submitterUserId): array{
|
||||
if($artistUrlName === null){
|
||||
throw new Exceptions\ArtistNotFoundException();
|
||||
}
|
||||
|
||||
$artwork->Name = HttpInput::Str(POST, 'artwork-name') ?? '';
|
||||
$artwork->CompletedYear = HttpInput::Int(POST, 'artwork-year');
|
||||
$artwork->CompletedYearIsCirca = HttpInput::Bool(POST, 'artwork-completed-year-is-circa') ?? false;
|
||||
$artwork->Tags = HttpInput::Str(POST, 'artwork-tags') ?? [];
|
||||
$artwork->Status = Enums\ArtworkStatusType::tryFrom(HttpInput::Str(POST, 'artwork-status') ?? '') ?? Enums\ArtworkStatusType::Unverified;
|
||||
$artwork->EbookUrl = HttpInput::Str(POST, 'artwork-ebook-url');
|
||||
$artwork->IsPublishedInUs = HttpInput::Bool(POST, 'artwork-is-published-in-us') ?? false;
|
||||
$artwork->PublicationYear = HttpInput::Int(POST, 'artwork-publication-year');
|
||||
$artwork->PublicationYearPageUrl = HttpInput::Str(POST, 'artwork-publication-year-page-url');
|
||||
$artwork->CopyrightPageUrl = HttpInput::Str(POST, 'artwork-copyright-page-url');
|
||||
$artwork->ArtworkPageUrl = HttpInput::Str(POST, 'artwork-artwork-page-url');
|
||||
$artwork->MuseumUrl = HttpInput::Str(POST, 'artwork-museum-url');
|
||||
$artwork->Exception = HttpInput::Str(POST, 'artwork-exception');
|
||||
$artwork->Notes = HttpInput::Str(POST, 'artwork-notes');
|
||||
// $status is only one of three special statuses, which are a subset of FilterArtwork() above:
|
||||
// null: same as "all"
|
||||
// "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 = '';
|
||||
$params = [];
|
||||
|
||||
return $artwork;
|
||||
if($status == 'all-admin'){
|
||||
$statusCondition = 'true';
|
||||
}
|
||||
elseif($status == 'all-submitter' && $submitterUserId !== null){
|
||||
$statusCondition = '(Status = ? or (Status = ? and SubmitterUserId = ?))';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
$params[] = Enums\ArtworkStatusType::Unverified->value;
|
||||
$params[] = $submitterUserId;
|
||||
}
|
||||
else{
|
||||
$statusCondition = 'Status = ?';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
}
|
||||
|
||||
$params[] = $artistUrlName; // a.UrlName
|
||||
|
||||
$artworks = Db::Query('
|
||||
SELECT art.*
|
||||
from Artworks art
|
||||
inner join Artists a using (ArtistId)
|
||||
where ' . $statusCondition . '
|
||||
and a.UrlName = ?
|
||||
order by art.Created desc', $params, Artwork::class);
|
||||
|
||||
return $artworks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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{
|
||||
// $status is either the string value of an ArtworkStatus enum, or one of these special statuses:
|
||||
// null: same as "all"
|
||||
// "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 = '';
|
||||
$params = [];
|
||||
|
||||
if($status === null || $status == 'all'){
|
||||
$statusCondition = 'Status = ?';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
}
|
||||
elseif($status == 'all-admin'){
|
||||
$statusCondition = 'true';
|
||||
}
|
||||
elseif($status == 'all-submitter' && $submitterUserId !== null){
|
||||
$statusCondition = '(Status = ? or (Status = ? and SubmitterUserId = ?))';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
$params[] = Enums\ArtworkStatusType::Unverified->value;
|
||||
$params[] = $submitterUserId;
|
||||
}
|
||||
elseif($status == 'unverified-submitter' && $submitterUserId !== null){
|
||||
$statusCondition = 'Status = ? and SubmitterUserId = ?';
|
||||
$params[] = Enums\ArtworkStatusType::Unverified->value;
|
||||
$params[] = $submitterUserId;
|
||||
}
|
||||
elseif($status == 'in-use'){
|
||||
$statusCondition = 'Status = ? and EbookUrl is not null';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
}
|
||||
elseif($status == Enums\ArtworkStatusType::Approved->value){
|
||||
$statusCondition = 'Status = ? and EbookUrl is null';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
}
|
||||
else{
|
||||
$statusCondition = 'Status = ?';
|
||||
$params[] = $status;
|
||||
}
|
||||
|
||||
$orderBy = 'art.Created desc';
|
||||
if($sort == Enums\ArtworkSortType::ArtistAlpha){
|
||||
$orderBy = 'a.Name';
|
||||
}
|
||||
elseif($sort == Enums\ArtworkSortType::CompletedNewest){
|
||||
$orderBy = 'art.CompletedYear desc';
|
||||
}
|
||||
|
||||
// Remove diacritics and non-alphanumeric characters, but preserve apostrophes
|
||||
if($query !== null && $query != ''){
|
||||
$query = trim(preg_replace('|[^a-zA-Z0-9\'’ ]|ius', ' ', Formatter::RemoveDiacritics($query)));
|
||||
}
|
||||
else{
|
||||
$query = '';
|
||||
}
|
||||
|
||||
// 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
|
||||
$limit = $perPage;
|
||||
$offset = (($page - 1) * $perPage);
|
||||
|
||||
if($query == ''){
|
||||
$artworksCount = Db::QueryInt('
|
||||
SELECT count(*)
|
||||
from Artworks art
|
||||
where ' . $statusCondition, $params);
|
||||
|
||||
$params[] = $limit;
|
||||
$params[] = $offset;
|
||||
|
||||
$artworks = Db::Query('
|
||||
SELECT art.*
|
||||
from Artworks art
|
||||
inner join Artists a USING (ArtistId)
|
||||
where ' . $statusCondition . '
|
||||
order by ' . $orderBy . '
|
||||
limit ?
|
||||
offset ?', $params, Artwork::class);
|
||||
}
|
||||
else{
|
||||
// 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);
|
||||
|
||||
// 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';
|
||||
|
||||
$params[] = $tokenizedQuery; // art.Name
|
||||
$params[] = $tokenizedQuery; // art.EbookUrl
|
||||
$params[] = $tokenizedQuery; // a.Name
|
||||
$params[] = $tokenizedQuery; // aan.Name
|
||||
$params[] = $tokenizedQuery; // t.Name
|
||||
|
||||
$artworksCount = Db::QueryInt('
|
||||
SELECT
|
||||
count(*)
|
||||
from
|
||||
(SELECT distinct
|
||||
ArtworkId
|
||||
from
|
||||
Artworks art
|
||||
inner join Artists a USING (ArtistId)
|
||||
left join ArtistAlternateNames aan USING (ArtistId)
|
||||
left join ArtworkTags at USING (ArtworkId)
|
||||
left join Tags t USING (TagId)
|
||||
where
|
||||
' . $statusCondition . '
|
||||
and (art.Name regexp ?
|
||||
or replace(art.EbookUrl, "_", " ") regexp ?
|
||||
or a.Name regexp ?
|
||||
or aan.Name regexp ?
|
||||
or t.Name regexp ?)
|
||||
group by art.ArtworkId) x', $params);
|
||||
|
||||
$params[] = $limit;
|
||||
$params[] = $offset;
|
||||
|
||||
$artworks = Db::Query('
|
||||
SELECT art.*
|
||||
from Artworks art
|
||||
inner join Artists a using (ArtistId)
|
||||
left join ArtistAlternateNames aan using (ArtistId)
|
||||
left join ArtworkTags at using (ArtworkId)
|
||||
left join Tags t using (TagId)
|
||||
where ' . $statusCondition . '
|
||||
and (art.Name regexp ?
|
||||
or replace(art.EbookUrl, "_", " ") regexp ?
|
||||
or a.Name regexp ?
|
||||
or aan.Name regexp ?
|
||||
or t.Name regexp ?)
|
||||
group by art.ArtworkId
|
||||
order by ' . $orderBy . '
|
||||
limit ?
|
||||
offset ?', $params, Artwork::class);
|
||||
}
|
||||
|
||||
return ['artworks' => $artworks, 'artworksCount' => $artworksCount];
|
||||
}
|
||||
|
||||
public function FillFromHttpPost(): void{
|
||||
|
|
|
@ -55,6 +55,17 @@ class Collection{
|
|||
return $result[0] ?? throw new Exceptions\CollectionNotFoundException();;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Collection>
|
||||
*/
|
||||
public static function GetAll(): array{
|
||||
return Db::Query('
|
||||
SELECT *
|
||||
from Collections
|
||||
order by Name asc
|
||||
', [], Collection::class);
|
||||
}
|
||||
|
||||
|
||||
// *******
|
||||
// METHODS
|
||||
|
|
155
lib/Ebook.php
155
lib/Ebook.php
|
@ -1,5 +1,4 @@
|
|||
<?
|
||||
|
||||
use Safe\DateTimeImmutable;
|
||||
|
||||
use function Safe\file_get_contents;
|
||||
|
@ -1853,4 +1852,158 @@ class Ebook{
|
|||
|
||||
return $result[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Ebook>
|
||||
*/
|
||||
public static function GetAll(): array{
|
||||
// Get all ebooks, unsorted.
|
||||
return Db::Query('
|
||||
SELECT *
|
||||
from Ebooks
|
||||
', [], Ebook::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Ebook>
|
||||
*/
|
||||
public static function GetAllByAuthor(string $urlPath): array{
|
||||
if(mb_strpos($urlPath, '_') === false){
|
||||
// Single author
|
||||
return Db::Query('
|
||||
SELECT e.*
|
||||
from Ebooks e
|
||||
inner join Contributors con using (EbookId)
|
||||
where con.MarcRole = "aut"
|
||||
and con.UrlName = ?
|
||||
order by e.EbookCreated desc
|
||||
', [$urlPath], Ebook::class);
|
||||
}
|
||||
else{
|
||||
// Multiple authors, e.g., `karl-marx_friedrich-engels`.
|
||||
$authors = explode('_', $urlPath);
|
||||
|
||||
$params = $authors;
|
||||
$params[] = sizeof($authors); // The number of authors in the URL must match the number of `Contributor` records.
|
||||
|
||||
return Db::Query('
|
||||
SELECT e.*
|
||||
from Ebooks e
|
||||
inner join Contributors con using (EbookId)
|
||||
where con.MarcRole = "aut"
|
||||
and con.UrlName in ' . Db::CreateSetSql($authors) . '
|
||||
group by e.EbookId
|
||||
having count(distinct con.UrlName) = ?
|
||||
order by e.EbookCreated desc
|
||||
', $params, Ebook::class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Ebook>
|
||||
*/
|
||||
public static function GetAllByCollection(string $collection): array{
|
||||
$ebooks = Db::Query('
|
||||
SELECT e.*
|
||||
from Ebooks e
|
||||
inner join CollectionEbooks ce using (EbookId)
|
||||
inner join Collections c using (CollectionId)
|
||||
where c.UrlName = ?
|
||||
order by ce.SequenceNumber, e.EbookCreated desc
|
||||
', [$collection], Ebook::class);
|
||||
|
||||
return $ebooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Ebook>
|
||||
*/
|
||||
public static function GetAllByRelated(Ebook $ebook, int $count, ?EbookTag $relatedTag): array{
|
||||
if($relatedTag !== null){
|
||||
$relatedEbooks = Db::Query('
|
||||
SELECT e.*
|
||||
from Ebooks e
|
||||
inner join EbookTags et using (EbookId)
|
||||
where et.TagId = ?
|
||||
and et.EbookId != ?
|
||||
order by RAND()
|
||||
limit ?
|
||||
', [$relatedTag->TagId, $ebook->EbookId, $count], Ebook::class);
|
||||
}
|
||||
else{
|
||||
$relatedEbooks = Db::Query('
|
||||
SELECT *
|
||||
from Ebooks
|
||||
where EbookId != ?
|
||||
order by RAND()
|
||||
limit ?
|
||||
', [$ebook->EbookId, $count], Ebook::class);
|
||||
}
|
||||
|
||||
return $relatedEbooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string> $tags
|
||||
*
|
||||
* @return array{ebooks: array<Ebook>, ebooksCount: int}
|
||||
*/
|
||||
public static function GetAllByFilter(string $query = null, array $tags = [], Enums\EbookSortType $sort = null, int $page = 1, int $perPage = EBOOKS_PER_PAGE): array{
|
||||
$limit = $perPage;
|
||||
$offset = (($page - 1) * $perPage);
|
||||
$joinContributors = '';
|
||||
$joinTags = '';
|
||||
$params = [];
|
||||
$whereCondition = 'where true';
|
||||
|
||||
$orderBy = 'e.EbookCreated desc';
|
||||
if($sort == Enums\EbookSortType::AuthorAlpha){
|
||||
$joinContributors = 'inner join Contributors con using (EbookId)';
|
||||
$whereCondition .= ' AND con.MarcRole = "aut"';
|
||||
$orderBy = 'con.SortName, e.EbookCreated desc';
|
||||
}
|
||||
elseif($sort == Enums\EbookSortType::ReadingEase){
|
||||
$orderBy = 'e.ReadingEase desc';
|
||||
}
|
||||
elseif($sort == Enums\EbookSortType::Length){
|
||||
$orderBy = 'e.WordCount';
|
||||
}
|
||||
|
||||
if(sizeof($tags) > 0 && !in_array('all', $tags)){ // 0 tags means "all ebooks"
|
||||
$joinTags = 'inner join EbookTags et using (EbookId)
|
||||
inner join Tags t using (TagId)';
|
||||
$whereCondition .= ' AND t.UrlName in ' . Db::CreateSetSql($tags) . ' ';
|
||||
$params = $tags;
|
||||
}
|
||||
|
||||
if($query !== null && $query != ''){
|
||||
$query = trim(preg_replace('|[^a-zA-Z0-9 ]|ius', ' ', Formatter::RemoveDiacritics($query)));
|
||||
$query = sprintf('"%s"', $query); // Require an exact match via double quotes.
|
||||
$whereCondition .= ' AND match(e.IndexableText) against(? IN BOOLEAN MODE) ';
|
||||
$params[] = $query;
|
||||
}
|
||||
|
||||
$ebooksCount = Db::QueryInt('
|
||||
SELECT count(distinct e.EbookId)
|
||||
from Ebooks e
|
||||
' . $joinContributors . '
|
||||
' . $joinTags . '
|
||||
' . $whereCondition . '
|
||||
', $params);
|
||||
|
||||
$params[] = $limit;
|
||||
$params[] = $offset;
|
||||
|
||||
$ebooks = Db::Query('
|
||||
SELECT distinct e.*
|
||||
from Ebooks e
|
||||
' . $joinContributors . '
|
||||
' . $joinTags . '
|
||||
' . $whereCondition . '
|
||||
order by ' . $orderBy . '
|
||||
limit ?
|
||||
offset ?', $params, Ebook::class);
|
||||
|
||||
return ['ebooks' => $ebooks, 'ebooksCount' => $ebooksCount];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,4 +93,18 @@ class EbookTag extends Tag{
|
|||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<EbookTag>
|
||||
*/
|
||||
public static function GetAll(): array{
|
||||
$tags = Db::Query('
|
||||
SELECT *
|
||||
from Tags t
|
||||
where Type = ?
|
||||
order by Name
|
||||
', [Enums\TagType::Ebook], EbookTag::class);
|
||||
|
||||
return $tags;
|
||||
}
|
||||
}
|
||||
|
|
8
lib/Enums/FeedType.php
Normal file
8
lib/Enums/FeedType.php
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?
|
||||
namespace Enums;
|
||||
|
||||
enum FeedType: string{
|
||||
case Atom = 'atom';
|
||||
case Opds = 'opds';
|
||||
case Rss = 'rss';
|
||||
}
|
391
lib/Library.php
391
lib/Library.php
|
@ -6,389 +6,8 @@ use function Safe\filemtime;
|
|||
use function Safe\filesize;
|
||||
use function Safe\glob;
|
||||
use function Safe\preg_replace;
|
||||
use function Safe\preg_split;
|
||||
|
||||
class Library{
|
||||
/**
|
||||
* @param array<string> $tags
|
||||
*
|
||||
* @return array{ebooks: array<Ebook>, ebooksCount: int}
|
||||
*/
|
||||
public static function FilterEbooks(string $query = null, array $tags = [], Enums\EbookSortType $sort = null, int $page = 1, int $perPage = EBOOKS_PER_PAGE): array{
|
||||
$limit = $perPage;
|
||||
$offset = (($page - 1) * $perPage);
|
||||
$joinContributors = '';
|
||||
$joinTags = '';
|
||||
$params = [];
|
||||
$whereCondition = 'where true';
|
||||
|
||||
$orderBy = 'e.EbookCreated desc';
|
||||
if($sort == Enums\EbookSortType::AuthorAlpha){
|
||||
$joinContributors = 'inner join Contributors con using (EbookId)';
|
||||
$whereCondition .= ' AND con.MarcRole = "aut"';
|
||||
$orderBy = 'con.SortName, e.EbookCreated desc';
|
||||
}
|
||||
elseif($sort == Enums\EbookSortType::ReadingEase){
|
||||
$orderBy = 'e.ReadingEase desc';
|
||||
}
|
||||
elseif($sort == Enums\EbookSortType::Length){
|
||||
$orderBy = 'e.WordCount';
|
||||
}
|
||||
|
||||
if(sizeof($tags) > 0 && !in_array('all', $tags)){ // 0 tags means "all ebooks"
|
||||
$joinTags = 'inner join EbookTags et using (EbookId)
|
||||
inner join Tags t using (TagId)';
|
||||
$whereCondition .= ' AND t.UrlName in ' . Db::CreateSetSql($tags) . ' ';
|
||||
$params = $tags;
|
||||
}
|
||||
|
||||
if($query !== null && $query != ''){
|
||||
$query = trim(preg_replace('|[^a-zA-Z0-9 ]|ius', ' ', Formatter::RemoveDiacritics($query)));
|
||||
$query = sprintf('"%s"', $query); // Require an exact match via double quotes.
|
||||
$whereCondition .= ' AND match(e.IndexableText) against(? IN BOOLEAN MODE) ';
|
||||
$params[] = $query;
|
||||
}
|
||||
|
||||
$ebooksCount = Db::QueryInt('
|
||||
SELECT count(distinct e.EbookId)
|
||||
from Ebooks e
|
||||
' . $joinContributors . '
|
||||
' . $joinTags . '
|
||||
' . $whereCondition . '
|
||||
', $params);
|
||||
|
||||
$params[] = $limit;
|
||||
$params[] = $offset;
|
||||
|
||||
$ebooks = Db::Query('
|
||||
SELECT distinct e.*
|
||||
from Ebooks e
|
||||
' . $joinContributors . '
|
||||
' . $joinTags . '
|
||||
' . $whereCondition . '
|
||||
order by ' . $orderBy . '
|
||||
limit ?
|
||||
offset ?', $params, Ebook::class);
|
||||
|
||||
return ['ebooks' => $ebooks, 'ebooksCount' => $ebooksCount];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Ebook>
|
||||
*/
|
||||
public static function GetEbooks(): array{
|
||||
// Get all ebooks, unsorted.
|
||||
return Db::Query('
|
||||
SELECT *
|
||||
from Ebooks
|
||||
', [], Ebook::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Ebook>
|
||||
*/
|
||||
public static function GetEbooksByAuthor(string $urlPath): array{
|
||||
if(mb_strpos($urlPath, '_') === false){
|
||||
// Single author
|
||||
return Db::Query('
|
||||
SELECT e.*
|
||||
from Ebooks e
|
||||
inner join Contributors con using (EbookId)
|
||||
where con.MarcRole = "aut"
|
||||
and con.UrlName = ?
|
||||
order by e.EbookCreated desc
|
||||
', [$urlPath], Ebook::class);
|
||||
}
|
||||
else{
|
||||
// Multiple authors, e.g., `karl-marx_friedrich-engels`.
|
||||
$authors = explode('_', $urlPath);
|
||||
|
||||
$params = $authors;
|
||||
$params[] = sizeof($authors); // The number of authors in the URL must match the number of `Contributor` records.
|
||||
|
||||
return Db::Query('
|
||||
SELECT e.*
|
||||
from Ebooks e
|
||||
inner join Contributors con using (EbookId)
|
||||
where con.MarcRole = "aut"
|
||||
and con.UrlName in ' . Db::CreateSetSql($authors) . '
|
||||
group by e.EbookId
|
||||
having count(distinct con.UrlName) = ?
|
||||
order by e.EbookCreated desc
|
||||
', $params, Ebook::class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Collection>
|
||||
*
|
||||
* @throws Exceptions\AppException
|
||||
*/
|
||||
public static function GetEbookCollections(): array{
|
||||
$collections = Db::Query('
|
||||
SELECT *
|
||||
from Collections
|
||||
', [], Collection::class);
|
||||
|
||||
$collator = Collator::create('en_US');
|
||||
if($collator === null){
|
||||
throw new Exceptions\AppException('Couldn\'t create collator object when getting collections.');
|
||||
}
|
||||
usort($collections, function(Collection $a, Collection $b) use($collator){
|
||||
$result = $collator->compare($a->GetSortedName(), $b->GetSortedName());
|
||||
return $result === false ? 0 : $result;
|
||||
});
|
||||
return $collections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Ebook>
|
||||
*/
|
||||
public static function GetEbooksByCollection(string $collection): array{
|
||||
$ebooks = Db::Query('
|
||||
SELECT e.*
|
||||
from Ebooks e
|
||||
inner join CollectionEbooks ce using (EbookId)
|
||||
inner join Collections c using (CollectionId)
|
||||
where c.UrlName = ?
|
||||
order by ce.SequenceNumber, e.EbookCreated desc
|
||||
', [$collection], Ebook::class);
|
||||
|
||||
return $ebooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Ebook>
|
||||
*/
|
||||
public static function GetRelatedEbooks(Ebook $ebook, int $count, ?EbookTag $relatedTag): array{
|
||||
if($relatedTag !== null){
|
||||
$relatedEbooks = Db::Query('
|
||||
SELECT e.*
|
||||
from Ebooks e
|
||||
inner join EbookTags et using (EbookId)
|
||||
where et.TagId = ?
|
||||
and et.EbookId != ?
|
||||
order by RAND()
|
||||
limit ?
|
||||
', [$relatedTag->TagId, $ebook->EbookId, $count], Ebook::class);
|
||||
}
|
||||
else{
|
||||
$relatedEbooks = Db::Query('
|
||||
SELECT *
|
||||
from Ebooks
|
||||
where EbookId != ?
|
||||
order by RAND()
|
||||
limit ?
|
||||
', [$ebook->EbookId, $count], Ebook::class);
|
||||
}
|
||||
|
||||
return $relatedEbooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<EbookTag>
|
||||
*/
|
||||
public static function GetTags(): array{
|
||||
$tags = Db::Query('
|
||||
SELECT *
|
||||
from Tags t
|
||||
where Type = "ebook"
|
||||
order by Name
|
||||
', [], EbookTag::class);
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{artworks: array<Artwork>, artworksCount: int}
|
||||
*/
|
||||
public static function FilterArtwork(?string $query = null, ?string $status = 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:
|
||||
// null: same as "all"
|
||||
// "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 = '';
|
||||
$params = [];
|
||||
|
||||
if($status === null || $status == 'all'){
|
||||
$statusCondition = 'Status = ?';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
}
|
||||
elseif($status == 'all-admin'){
|
||||
$statusCondition = 'true';
|
||||
}
|
||||
elseif($status == 'all-submitter' && $submitterUserId !== null){
|
||||
$statusCondition = '(Status = ? or (Status = ? and SubmitterUserId = ?))';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
$params[] = Enums\ArtworkStatusType::Unverified->value;
|
||||
$params[] = $submitterUserId;
|
||||
}
|
||||
elseif($status == 'unverified-submitter' && $submitterUserId !== null){
|
||||
$statusCondition = 'Status = ? and SubmitterUserId = ?';
|
||||
$params[] = Enums\ArtworkStatusType::Unverified->value;
|
||||
$params[] = $submitterUserId;
|
||||
}
|
||||
elseif($status == 'in-use'){
|
||||
$statusCondition = 'Status = ? and EbookUrl is not null';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
}
|
||||
elseif($status == Enums\ArtworkStatusType::Approved->value){
|
||||
$statusCondition = 'Status = ? and EbookUrl is null';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
}
|
||||
else{
|
||||
$statusCondition = 'Status = ?';
|
||||
$params[] = $status;
|
||||
}
|
||||
|
||||
$orderBy = 'art.Created desc';
|
||||
if($sort == Enums\ArtworkSortType::ArtistAlpha){
|
||||
$orderBy = 'a.Name';
|
||||
}
|
||||
elseif($sort == Enums\ArtworkSortType::CompletedNewest){
|
||||
$orderBy = 'art.CompletedYear desc';
|
||||
}
|
||||
|
||||
// Remove diacritics and non-alphanumeric characters, but preserve apostrophes
|
||||
if($query !== null && $query != ''){
|
||||
$query = trim(preg_replace('|[^a-zA-Z0-9\'’ ]|ius', ' ', Formatter::RemoveDiacritics($query)));
|
||||
}
|
||||
else{
|
||||
$query = '';
|
||||
}
|
||||
|
||||
// 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
|
||||
$limit = $perPage;
|
||||
$offset = (($page - 1) * $perPage);
|
||||
|
||||
if($query == ''){
|
||||
$artworksCount = Db::QueryInt('
|
||||
SELECT count(*)
|
||||
from Artworks art
|
||||
where ' . $statusCondition, $params);
|
||||
|
||||
$params[] = $limit;
|
||||
$params[] = $offset;
|
||||
|
||||
$artworks = Db::Query('
|
||||
SELECT art.*
|
||||
from Artworks art
|
||||
inner join Artists a USING (ArtistId)
|
||||
where ' . $statusCondition . '
|
||||
order by ' . $orderBy . '
|
||||
limit ?
|
||||
offset ?', $params, Artwork::class);
|
||||
}
|
||||
else{
|
||||
// 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);
|
||||
|
||||
// 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';
|
||||
|
||||
$params[] = $tokenizedQuery; // art.Name
|
||||
$params[] = $tokenizedQuery; // art.EbookUrl
|
||||
$params[] = $tokenizedQuery; // a.Name
|
||||
$params[] = $tokenizedQuery; // aan.Name
|
||||
$params[] = $tokenizedQuery; // t.Name
|
||||
|
||||
$artworksCount = Db::QueryInt('
|
||||
SELECT
|
||||
count(*)
|
||||
from
|
||||
(SELECT distinct
|
||||
ArtworkId
|
||||
from
|
||||
Artworks art
|
||||
inner join Artists a USING (ArtistId)
|
||||
left join ArtistAlternateNames aan USING (ArtistId)
|
||||
left join ArtworkTags at USING (ArtworkId)
|
||||
left join Tags t USING (TagId)
|
||||
where
|
||||
' . $statusCondition . '
|
||||
and (art.Name regexp ?
|
||||
or replace(art.EbookUrl, "_", " ") regexp ?
|
||||
or a.Name regexp ?
|
||||
or aan.Name regexp ?
|
||||
or t.Name regexp ?)
|
||||
group by art.ArtworkId) x', $params);
|
||||
|
||||
$params[] = $limit;
|
||||
$params[] = $offset;
|
||||
|
||||
$artworks = Db::Query('
|
||||
SELECT art.*
|
||||
from Artworks art
|
||||
inner join Artists a using (ArtistId)
|
||||
left join ArtistAlternateNames aan using (ArtistId)
|
||||
left join ArtworkTags at using (ArtworkId)
|
||||
left join Tags t using (TagId)
|
||||
where ' . $statusCondition . '
|
||||
and (art.Name regexp ?
|
||||
or replace(art.EbookUrl, "_", " ") regexp ?
|
||||
or a.Name regexp ?
|
||||
or aan.Name regexp ?
|
||||
or t.Name regexp ?)
|
||||
group by art.ArtworkId
|
||||
order by ' . $orderBy . '
|
||||
limit ?
|
||||
offset ?', $params, Artwork::class);
|
||||
}
|
||||
|
||||
return ['artworks' => $artworks, 'artworksCount' => $artworksCount];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Artwork>
|
||||
*
|
||||
* @throws Exceptions\ArtistNotFoundException
|
||||
*/
|
||||
public static function GetArtworksByArtist(?string $artistUrlName, ?string $status, ?int $submitterUserId): array{
|
||||
if($artistUrlName === null){
|
||||
throw new Exceptions\ArtistNotFoundException();
|
||||
}
|
||||
|
||||
// $status is only one of three special statuses, which are a subset of FilterArtwork() above:
|
||||
// null: same as "all"
|
||||
// "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 = '';
|
||||
$params = [];
|
||||
|
||||
if($status == 'all-admin'){
|
||||
$statusCondition = 'true';
|
||||
}
|
||||
elseif($status == 'all-submitter' && $submitterUserId !== null){
|
||||
$statusCondition = '(Status = ? or (Status = ? and SubmitterUserId = ?))';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
$params[] = Enums\ArtworkStatusType::Unverified->value;
|
||||
$params[] = $submitterUserId;
|
||||
}
|
||||
else{
|
||||
$statusCondition = 'Status = ?';
|
||||
$params[] = Enums\ArtworkStatusType::Approved->value;
|
||||
}
|
||||
|
||||
$params[] = $artistUrlName; // a.UrlName
|
||||
|
||||
$artworks = Db::Query('
|
||||
SELECT art.*
|
||||
from Artworks art
|
||||
inner join Artists a using (ArtistId)
|
||||
where ' . $statusCondition . '
|
||||
and a.UrlName = ?
|
||||
order by art.Created desc', $params, Artwork::class);
|
||||
|
||||
return $artworks;
|
||||
}
|
||||
|
||||
private static function FillBulkDownloadObject(string $dir, string $downloadType, string $urlRoot): stdClass{
|
||||
$obj = new stdClass();
|
||||
|
||||
|
@ -614,14 +233,4 @@ class Library{
|
|||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Artist>
|
||||
*/
|
||||
public static function GetArtists(): array{
|
||||
return Db::Query('
|
||||
SELECT *
|
||||
from Artists
|
||||
order by Name asc', [], Artist::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ function CreateZip(string $filePath, array $ebooks, string $type, string $webRoo
|
|||
}
|
||||
|
||||
// Iterate over all ebooks and arrange them by publication month.
|
||||
foreach(Library::GetEbooks() as $ebook){
|
||||
foreach(Ebook::GetAll() as $ebook){
|
||||
$timestamp = $ebook->EbookCreated->format('Y-m');
|
||||
$updatedTimestamp = $ebook->EbookUpdated->getTimestamp();
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ function SaveFeed(Feed $feed, bool $force, ?string $label = null, ?string $label
|
|||
* @param array<string, array<Ebook>> $ebooks
|
||||
*/
|
||||
function CreateOpdsCollectionFeed(string $name, string $url, string $description, array $collections, array $ebooks, DateTimeImmutable $now, string $webRoot, OpdsNavigationFeed $opdsRoot, bool $force): void{
|
||||
$collator = Collator::create('en_US'); // Used for sorting letters with diacritics like in author names
|
||||
$collator = Collator::create('en_US'); // Used for sorting letters with diacritics, like in author names.
|
||||
|
||||
if($collator === null){
|
||||
return;
|
||||
|
@ -97,7 +97,7 @@ foreach($dirs as $dir){
|
|||
}
|
||||
|
||||
// Iterate over all ebooks to build the various feeds.
|
||||
foreach(Library::GetEbooks() as $ebook){
|
||||
foreach(Ebook::GetAll() as $ebook){
|
||||
$allEbooks[] = $ebook;
|
||||
$newestEbooks[] = $ebook;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ $isEditForm = $isEditForm ?? false;
|
|||
<span>Name</span>
|
||||
<span>For existing artists, leave the year of death blank.</span>
|
||||
<datalist id="artist-names">
|
||||
<? foreach(Library::GetArtists() as $artist){ ?>
|
||||
<? foreach(Artist::GetAll() as $artist){ ?>
|
||||
<option value="<?= Formatter::EscapeHtml($artist->Name) ?>"><?= Formatter::EscapeHtml($artist->Name) ?>, d. <? if($artist->DeathYear !== null){ ?><?= $artist->DeathYear ?><? }else{ ?>unknown<? } ?></option>
|
||||
<? foreach(($artist->AlternateNames ?? []) as $alternateName){ ?>
|
||||
<option value="<?= Formatter::EscapeHtml($alternateName) ?>"><?= Formatter::EscapeHtml($alternateName) ?>, d. <? if($artist->DeathYear !== null){ ?><?= Formatter::EscapeHtml((string)$artist->DeathYear) ?><? }else{ ?>unknown<? } ?></option>
|
||||
|
|
|
@ -12,7 +12,7 @@ $isAllSelected = sizeof($tags) == 0 || in_array('all', $tags);
|
|||
<label class="tags">Subjects
|
||||
<select <? if(!Template::IsEreaderBrowser()){ ?> multiple="multiple"<? } ?> name="tags[]" size="1">
|
||||
<option value="all">All</option>
|
||||
<? foreach(Library::GetTags() as $tag){ ?>
|
||||
<? foreach(EbookTag::GetAll() as $tag){ ?>
|
||||
<option value="<?= $tag->UrlName ?>"<? if(!$isAllSelected && in_array($tag->UrlName, $tags)){ ?> selected="selected"<? } ?>><?= Formatter::EscapeHtml($tag->Name) ?></option>
|
||||
<? } ?>
|
||||
</select>
|
||||
|
|
|
@ -14,7 +14,7 @@ if($isSubmitterView){
|
|||
}
|
||||
|
||||
try{
|
||||
$artworks = Library::GetArtworksByArtist(HttpInput::Str(GET, 'artist-url-name'), $filterArtworkStatus, $submitterUserId);
|
||||
$artworks = Artwork::GetAllByArtist(HttpInput::Str(GET, 'artist-url-name'), $filterArtworkStatus, $submitterUserId);
|
||||
|
||||
if(sizeof($artworks) == 0){
|
||||
throw new Exceptions\ArtistNotFoundException();
|
||||
|
|
|
@ -67,7 +67,7 @@ try{
|
|||
$totalArtworkCount = sizeof($artworks);
|
||||
}
|
||||
else{
|
||||
$result = Library::FilterArtwork($query, $filterArtworkStatus, $sort, $submitterUserId, $page, $perPage);
|
||||
$result = Artwork::GetAllByFilter($query, $filterArtworkStatus, $sort, $submitterUserId, $page, $perPage);
|
||||
$artworks = $result['artworks'];
|
||||
$totalArtworkCount = $result['artworksCount'];
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ try{
|
|||
|
||||
$exceptionRedirectUrl = $originalArtwork->EditUrl;
|
||||
|
||||
$artwork = Artwork::FromHttpPost();
|
||||
$artwork = new Artwork();
|
||||
$artwork->FillFromHttpPost();
|
||||
$artwork->ArtworkId = $originalArtwork->ArtworkId;
|
||||
$artwork->Created = $originalArtwork->Created;
|
||||
$artwork->SubmitterUserId = $originalArtwork->SubmitterUserId;
|
||||
|
|
|
@ -7,7 +7,7 @@ try{
|
|||
$collectionName = '';
|
||||
$collectionType = '';
|
||||
|
||||
$ebooks = Library::GetEbooksByCollection($collection);
|
||||
$ebooks = Ebook::GetAllByCollection($collection);
|
||||
// Get the *actual* name of the collection, in case there are accent marks (like "Arsène Lupin")
|
||||
if(sizeof($ebooks) > 0){
|
||||
foreach($ebooks[0]->CollectionMemberships as $cm){
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?
|
||||
$collections = Library::GetEbookCollections();
|
||||
$collections = Collection::GetAll();
|
||||
|
||||
?><?= Template::Header(['title' => 'Ebook Collections', 'highlight' => '', 'description' => 'Browse collections of Standard Ebooks.']) ?>
|
||||
<main>
|
||||
|
|
|
@ -12,7 +12,7 @@ try{
|
|||
throw new Exceptions\AuthorNotFoundException();
|
||||
}
|
||||
|
||||
$ebooks = Library::GetEbooksByAuthor($urlPath);
|
||||
$ebooks = Ebook::GetAllByAuthor($urlPath);
|
||||
|
||||
if(sizeof($ebooks) == 0){
|
||||
throw new Exceptions\AuthorNotFoundException();
|
||||
|
|
|
@ -68,7 +68,7 @@ try{
|
|||
if(sizeof($ebook->Tags) > 0){
|
||||
$carouselTag = $ebook->Tags[rand(0, sizeof($ebook->Tags) - 1)];
|
||||
}
|
||||
$carousel = Library::GetRelatedEbooks($ebook, $targetCarouselSize, $carouselTag);
|
||||
$carousel = Ebook::GetAllByRelated($ebook, $targetCarouselSize, $carouselTag);
|
||||
}
|
||||
catch(Exceptions\SeeOtherEbookException $ex){
|
||||
http_response_code(301);
|
||||
|
|
|
@ -35,7 +35,7 @@ try{
|
|||
$tags = [];
|
||||
}
|
||||
|
||||
$result = Library::FilterEbooks($query != '' ? $query : null, $tags, $sort, $page, $perPage);
|
||||
$result = Ebook::GetAllByFilter($query != '' ? $query : null, $tags, $sort, $page, $perPage);
|
||||
$ebooks = $result['ebooks'];
|
||||
$totalEbooks = $result['ebooksCount'];
|
||||
$pageTitle = 'Browse Standard Ebooks';
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
<?
|
||||
use function Safe\preg_match;
|
||||
|
||||
$type = '';
|
||||
$feedType = '';
|
||||
preg_match('/^\/feeds\/(opds|rss|atom)/ius', $_SERVER['REQUEST_URI'], $matches);
|
||||
|
||||
if(sizeof($matches) > 0){
|
||||
$type = $matches[1];
|
||||
$feedType = Enums\FeedType::tryFrom(strtolower($matches[1]));
|
||||
}
|
||||
|
||||
$title = 'Standard Ebooks Ebook Feeds';
|
||||
if($type == 'opds'){
|
||||
if($feedType == Enums\FeedType::Opds){
|
||||
$title = 'The Standard Ebooks OPDS Feed';
|
||||
}
|
||||
|
||||
if($type == 'rss'){
|
||||
if($feedType == Enums\FeedType::Rss){
|
||||
$title = 'Standard Ebooks RSS Feeds';
|
||||
}
|
||||
|
||||
if($type == 'atom'){
|
||||
if($feedType == Enums\FeedType::Atom){
|
||||
$title = 'Standard Ebooks Atom Feeds';
|
||||
}
|
||||
|
||||
?><?= Template::Header(['title' => 'The Standard Ebooks OPDS feed', 'highlight' => '', 'description' => 'Get access to the Standard Ebooks OPDS feed for use in ereading programs in scripting.']) ?>
|
||||
<main>
|
||||
<section class="narrow has-hero">
|
||||
<? if($type == 'opds'){ ?>
|
||||
<? if($feedType == Enums\FeedType::Opds){ ?>
|
||||
<h1>The Standard Ebooks OPDS Feed</h1>
|
||||
<? }elseif($type == 'rss'){ ?>
|
||||
<? }elseif($feedType == Enums\FeedType::Rss){ ?>
|
||||
<h1>Standard Ebooks RSS Feeds</h1>
|
||||
<? }elseif($type == 'atom'){ ?>
|
||||
<? }elseif($feedType == Enums\FeedType::Atom){ ?>
|
||||
<h1>Standard Ebooks Atom Feeds</h1>
|
||||
<? }else{ ?>
|
||||
<h1>Standard Ebooks Ebook Feeds</h1>
|
||||
|
|
|
@ -9,7 +9,7 @@ try{
|
|||
$count = HttpInput::Int(GET, 'per-page') ?? EBOOKS_PER_PAGE;
|
||||
|
||||
if($query !== ''){
|
||||
$ebooks = Library::FilterEbooks($query, [], Enums\EbookSortType::Newest, $startPage, $count)['ebooks'];
|
||||
$ebooks = Ebook::GetAllByFilter($query, [], Enums\EbookSortType::Newest, $startPage, $count)['ebooks'];
|
||||
}
|
||||
}
|
||||
catch(\Exception){
|
||||
|
|
|
@ -5,7 +5,6 @@ $author = HttpInput::Str(GET, 'author');
|
|||
$collection = HttpInput::Str(GET, 'collection');
|
||||
$name = null;
|
||||
$target = null;
|
||||
$feedTypes = ['opds', 'atom', 'rss'];
|
||||
$feedTitle = '';
|
||||
$feedUrl = '';
|
||||
$title = '';
|
||||
|
@ -56,33 +55,33 @@ catch(Exceptions\CollectionNotFoundException){
|
|||
<article>
|
||||
<h1>Ebook Feeds for <?= Formatter::EscapeHtml($label) ?></h1>
|
||||
<?= Template::FeedHowTo() ?>
|
||||
<? foreach($feedTypes as $type){ ?>
|
||||
<section id="ebooks-by-<?= $type ?>">
|
||||
<? foreach(Enums\FeedType::cases() as $feedType){ ?>
|
||||
<section id="ebooks-by-<?= $feedType->value ?>">
|
||||
<h2>
|
||||
<? if($type == 'rss'){ ?>
|
||||
<? if($feedType == Enums\FeedType::Rss){ ?>
|
||||
RSS 2.0
|
||||
<? } ?>
|
||||
<? if($type == 'atom'){ ?>
|
||||
<? if($feedType == Enums\FeedType::Atom){ ?>
|
||||
Atom 1.0
|
||||
<? } ?>
|
||||
<? if($type == 'opds'){ ?>
|
||||
<? if($feedType == Enums\FeedType::Opds){ ?>
|
||||
OPDS 1.2
|
||||
<? } ?>
|
||||
Feed
|
||||
</h2>
|
||||
<? if($type == 'opds'){ ?>
|
||||
<? if($feedType == Enums\FeedType::Opds){ ?>
|
||||
<p>Import this feed into your ereader app to get access to these ebooks directly in your ereader.</p>
|
||||
<? } ?>
|
||||
<? if($type == 'atom'){ ?>
|
||||
<? if($feedType == Enums\FeedType::Atom){ ?>
|
||||
<p>Get updates in your <a href="https://en.wikipedia.org/wiki/Comparison_of_feed_aggregators">RSS client</a> whenever a new ebook is released, or parse this feed for easy scripting.</p>
|
||||
<? } ?>
|
||||
<? if($type == 'rss'){ ?>
|
||||
<? if($feedType == Enums\FeedType::Rss){ ?>
|
||||
<p>The predecessor of Atom, compatible with most RSS clients.</p>
|
||||
<? } ?>
|
||||
<ul class="feed">
|
||||
<li>
|
||||
<p><a href="/feeds/<?= $type ?>/<?= $name ?>/<?= $target?>"><?= Formatter::EscapeHtml($label) ?></a></p>
|
||||
<p class="url"><? if(isset(Session::$User->Email)){ ?>https://<?= rawurlencode(Session::$User->Email) ?>@<?= SITE_DOMAIN ?><? }else{ ?><?= SITE_URL ?><? } ?>/feeds/<?= $type ?>/<?= $name ?>/<?= $target?></p>
|
||||
<p><a href="/feeds/<?= $feedType->value ?>/<?= $name ?>/<?= $target?>"><?= Formatter::EscapeHtml($label) ?></a></p>
|
||||
<p class="url"><? if(isset(Session::$User->Email)){ ?>https://<?= rawurlencode(Session::$User->Email) ?>@<?= SITE_DOMAIN ?><? }else{ ?><?= SITE_URL ?><? } ?>/feeds/<?= $feedType->value ?>/<?= $name ?>/<?= $target?></p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
|
|
@ -9,7 +9,7 @@ try{
|
|||
$count = HttpInput::Int(GET, 'per-page') ?? EBOOKS_PER_PAGE;
|
||||
|
||||
if($query !== ''){
|
||||
$ebooks = Library::FilterEbooks($query, [], Enums\EbookSortType::Newest, $startPage, $count)['ebooks'];
|
||||
$ebooks = Ebook::GetAllByFilter($query, [], Enums\EbookSortType::Newest, $startPage, $count)['ebooks'];
|
||||
}
|
||||
}
|
||||
catch(\Exception){
|
||||
|
|
|
@ -9,7 +9,7 @@ try{
|
|||
$count = HttpInput::Int(GET, 'per-page') ?? EBOOKS_PER_PAGE;
|
||||
|
||||
if($query !== ''){
|
||||
$ebooks = Library::FilterEbooks($query, [], Enums\EbookSortType::Newest, $startPage, $count)['ebooks'];
|
||||
$ebooks = Ebook::GetAllByFilter($query, [], Enums\EbookSortType::Newest, $startPage, $count)['ebooks'];
|
||||
}
|
||||
}
|
||||
catch(\Exception){
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue