From d4c7703cf09a07d738641db451981bc65bb883f9 Mon Sep 17 00:00:00 2001 From: Alex Cabal Date: Mon, 11 Nov 2024 13:58:10 -0600 Subject: [PATCH] Restructure how incorrect ebook URLs are redirected --- lib/Constants.php | 32 ++++++------- lib/Ebook.php | 18 +++++-- lib/Exceptions/SeeOtherEbookException.php | 11 ----- templates/EbookGrid.php | 2 +- www/ebooks/get.php | 50 ++++++++------------ www/ebooks/public-domain-day-placeholder.php | 21 ++++---- 6 files changed, 62 insertions(+), 72 deletions(-) delete mode 100644 lib/Exceptions/SeeOtherEbookException.php diff --git a/lib/Constants.php b/lib/Constants.php index f2cfcf3b..0e4f9235 100644 --- a/lib/Constants.php +++ b/lib/Constants.php @@ -106,20 +106,20 @@ const DONATION_DRIVE_COUNTER_END = new DateTimeImmutable('May 8, 2022 23:59:00 A const PD_DAY_YEAR = 2025; const PD_DAY_DRAFT_PATH = '/standardebooks.org/drafts/' . PD_DAY_YEAR; const PD_DAY_EBOOKS = [ - 'graham-greene/the-man-within' => ['author' => 'Graham Greene', 'title' => 'The Man Within'], - 'c-s-forester/brown-on-resolution' => ['author' => 'C. S. Forester', 'title' => 'Brown on Resolution'], - 'dashiell-hammett/red-harvest' => ['author' => 'Dashiell Hammett', 'title' => 'Red Harvest'], - 'dashiell-hammett/the-dain-curse' => ['author' => 'Dashiell Hammett', 'title' => 'The Dain Curse'], - 'erich-maria-remarque/all-quiet-on-the-western-front/a-w-wheen' => ['author' => 'Erich Maria Remarque', 'title' => 'All Quiet on the Western Front', 'translator' => 'A. W. Wheen'], - 'ernest-hemingway/a-farewell-to-arms' => ['author' => 'Ernest Heminway', 'title' => 'A Farewell to Arms'], - 'j-b-priestley/the-good-companions' => ['author' => 'J. B. Priestley', 'title' => 'The Good Companions'], - 'john-steinbeck/cup-of-gold' => ['author' => 'John Steinbeck', 'title' => 'Cup of Gold'], - 'oliver-la-farge/laughing-boy' => ['author' => 'Oliver La Farge', 'title' => 'Laughing Boy'], - 'william-faulkner/the-sound-and-the-fury' => ['author' => 'William Faulkner', 'title' => 'The Sound and the Fury'], - 'mahatma-gandhi/the-story-of-my-experiments-with-truth/mahadev-desai' => ['author' => 'Mahatma Gandhi', 'title' => 'The Story of My Experiments with Truth'], - 'arthur-conan-doyle/the-maracot-deep' => ['author' => 'Arthur Conan Doyle', 'title' => 'The Maracot Deep'], - 'sinclair-lewis/dodsworth' => ['author' => 'Sinclair Lewis', 'title' => 'Dodsworth'], - 'thomas-wolfe/look-homeward-angel' => ['author' => 'Thomas Wolfe', 'title' => 'Look Homeward, Angel'], - 'lloyd-c-douglas/magnificent-obsession' => ['author' => 'Lloyd C. Dougals', 'title' => 'Magnificent Obsession'], - 'edith-wharton/hudson-river-bracketed' => ['author' => 'Edith Wharton', 'title' => 'Hudson River Bracketed'] + EBOOKS_IDENTIFIER_PREFIX . 'graham-greene/the-man-within' => ['author' => 'Graham Greene', 'title' => 'The Man Within'], + EBOOKS_IDENTIFIER_PREFIX . 'c-s-forester/brown-on-resolution' => ['author' => 'C. S. Forester', 'title' => 'Brown on Resolution'], + EBOOKS_IDENTIFIER_PREFIX . 'dashiell-hammett/red-harvest' => ['author' => 'Dashiell Hammett', 'title' => 'Red Harvest'], + EBOOKS_IDENTIFIER_PREFIX . 'dashiell-hammett/the-dain-curse' => ['author' => 'Dashiell Hammett', 'title' => 'The Dain Curse'], + EBOOKS_IDENTIFIER_PREFIX . 'erich-maria-remarque/all-quiet-on-the-western-front/a-w-wheen' => ['author' => 'Erich Maria Remarque', 'title' => 'All Quiet on the Western Front', 'translator' => 'A. W. Wheen'], + EBOOKS_IDENTIFIER_PREFIX . 'ernest-hemingway/a-farewell-to-arms' => ['author' => 'Ernest Heminway', 'title' => 'A Farewell to Arms'], + EBOOKS_IDENTIFIER_PREFIX . 'j-b-priestley/the-good-companions' => ['author' => 'J. B. Priestley', 'title' => 'The Good Companions'], + EBOOKS_IDENTIFIER_PREFIX . 'john-steinbeck/cup-of-gold' => ['author' => 'John Steinbeck', 'title' => 'Cup of Gold'], + EBOOKS_IDENTIFIER_PREFIX . 'oliver-la-farge/laughing-boy' => ['author' => 'Oliver La Farge', 'title' => 'Laughing Boy'], + EBOOKS_IDENTIFIER_PREFIX . 'william-faulkner/the-sound-and-the-fury' => ['author' => 'William Faulkner', 'title' => 'The Sound and the Fury'], + EBOOKS_IDENTIFIER_PREFIX . 'mahatma-gandhi/the-story-of-my-experiments-with-truth/mahadev-desai' => ['author' => 'Mahatma Gandhi', 'title' => 'The Story of My Experiments with Truth'], + EBOOKS_IDENTIFIER_PREFIX . 'arthur-conan-doyle/the-maracot-deep' => ['author' => 'Arthur Conan Doyle', 'title' => 'The Maracot Deep'], + EBOOKS_IDENTIFIER_PREFIX . 'sinclair-lewis/dodsworth' => ['author' => 'Sinclair Lewis', 'title' => 'Dodsworth'], + EBOOKS_IDENTIFIER_PREFIX . 'thomas-wolfe/look-homeward-angel' => ['author' => 'Thomas Wolfe', 'title' => 'Look Homeward, Angel'], + EBOOKS_IDENTIFIER_PREFIX . 'lloyd-c-douglas/magnificent-obsession' => ['author' => 'Lloyd C. Dougals', 'title' => 'Magnificent Obsession'], + EBOOKS_IDENTIFIER_PREFIX . 'edith-wharton/hudson-river-bracketed' => ['author' => 'Edith Wharton', 'title' => 'Hudson River Bracketed'] ]; diff --git a/lib/Ebook.php b/lib/Ebook.php index 244e9d4f..888e4b5e 100644 --- a/lib/Ebook.php +++ b/lib/Ebook.php @@ -766,6 +766,7 @@ class Ebook{ foreach($xml->xpath('/package/metadata/meta[@property="se:subject"]') ?: [] as $tag){ $ebookTag = new EbookTag(); $ebookTag->Name = $tag; + $ebookTag->UrlName = Formatter::MakeUrlSafe($ebookTag->Name); $tags[] = $ebookTag; } $ebook->Tags = $tags; @@ -1855,17 +1856,26 @@ class Ebook{ throw new Exceptions\EbookNotFoundException('Invalid identifier: ' . $identifier); } - $result = Db::Query(' + return Db::Query(' SELECT * from Ebooks where Identifier = ? - ', [$identifier], Ebook::class); + ', [$identifier], Ebook::class)[0] ?? throw new Exceptions\EbookNotFoundException('Invalid identifier: ' . $identifier); + } - if(sizeof($result) == 0){ + /** + * @throws Exceptions\EbookNotFoundException + */ + public static function GetByIdentifierStartingWith(?string $identifier): Ebook{ + if($identifier === null){ throw new Exceptions\EbookNotFoundException('Invalid identifier: ' . $identifier); } - return $result[0]; + return Db::Query(' + SELECT * + from Ebooks + where Identifier like concat(?, "%") + ', [$identifier], Ebook::class)[0] ?? throw new Exceptions\EbookNotFoundException('Invalid identifier: ' . $identifier); } /** diff --git a/lib/Exceptions/SeeOtherEbookException.php b/lib/Exceptions/SeeOtherEbookException.php deleted file mode 100644 index b20032ab..00000000 --- a/lib/Exceptions/SeeOtherEbookException.php +++ /dev/null @@ -1,11 +0,0 @@ -Url = $url; - parent::__construct('This ebook is at a different URL: ' . $url); - } -} diff --git a/templates/EbookGrid.php b/templates/EbookGrid.php index 94546b63..dc347880 100644 --- a/templates/EbookGrid.php +++ b/templates/EbookGrid.php @@ -37,7 +37,7 @@ $collection = $collection ?? null;
- ContributorsHtml !== null){ ?> + ContributorsHtml != ''){ ?>

ContributorsHtml, '.') ?>

diff --git a/www/ebooks/get.php b/www/ebooks/get.php index d1fb7d5a..b36b1000 100644 --- a/www/ebooks/get.php +++ b/www/ebooks/get.php @@ -15,30 +15,7 @@ $carouselTag = null; $targetCarouselSize = 5; try{ - $urlPath = trim(str_replace('.', '', HttpInput::Str(GET, 'url-path') ?? ''), '/'); // Contains the portion of the URL (without query string) that comes after `https://standardebooks.org/ebooks/`. - $wwwFilesystemPath = EBOOKS_DIST_PATH . $urlPath; // Path to the deployed WWW files for this ebook. - - if($urlPath == '' || mb_stripos($wwwFilesystemPath, EBOOKS_DIST_PATH) !== 0){ - // Ensure the path exists and that the root is in our www directory. - throw new Exceptions\EbookNotFoundException(); - } - - // Were we passed the author and a work but not the translator? - // For example: - // Instead of: . - // We can tell because if so, the dir we are passed will exist, but there will be no `src` folder. - if(is_dir($wwwFilesystemPath) && !is_dir($wwwFilesystemPath . '/src')){ - /** @var DirectoryIterator $file */ - foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($wwwFilesystemPath)) as $file){ - // This iterator will do a deep scan on the directory. When we hit another directory, the filename will be `.` and the path will contain the directory path. - // We want to find where the `src` directory is, and the directory directly below that will be the final web URL we're looking for. - if($file->getFilename() == '.' && preg_match('|/src$|ius', $file->getPath())){ - throw new Exceptions\SeeOtherEbookException(preg_replace(['|' . WEB_ROOT . '|ius', '|/src$|ius'], '', $file->getPath())); - } - } - } - - $identifier = EBOOKS_IDENTIFIER_PREFIX . $urlPath; + $identifier = EBOOKS_IDENTIFIER_PREFIX . trim(str_replace('.', '', HttpInput::Str(GET, 'url-path') ?? ''), '/'); // Contains the portion of the URL (without query string) that comes after `https://standardebooks.org/ebooks/`. $ebook = Ebook::GetByIdentifier($identifier); @@ -68,16 +45,27 @@ try{ if(sizeof($ebook->Tags) > 0){ $carouselTag = $ebook->Tags[rand(0, sizeof($ebook->Tags) - 1)]; } + $carousel = Ebook::GetAllByRelated($ebook, $targetCarouselSize, $carouselTag); } -catch(Exceptions\SeeOtherEbookException $ex){ - http_response_code(301); - header('Location: ' . $ex->Url); - exit(); -} catch(Exceptions\EbookNotFoundException){ + // Were we passed the author and a work but not the translator? + // For example: + // Instead of: . + try{ + $ebook = Ebook::GetByIdentifierStartingWith($identifier); + + // Found, redirect. + http_response_code(301); + header('Location: ' . $ebook->Url); + exit(); + } + catch(Exceptions\EbookNotFoundException){ + // Still not found, continue. + } + // Are we accessing a placeholder for a Public Domain Day book that is not yet released? - if(array_key_exists($urlPath, PD_DAY_EBOOKS)){ + if(array_key_exists($identifier, PD_DAY_EBOOKS)){ require('/standardebooks.org/web/www/ebooks/public-domain-day-placeholder.php'); exit(); } @@ -127,7 +115,7 @@ catch(Exceptions\EbookNotFoundException){