mirror of
https://github.com/standardebooks/web.git
synced 2025-07-05 22:30:30 -04:00
Bump PHPStan check level to max and add final round of type hints
This commit is contained in:
parent
110c091a7b
commit
70ae877dd8
15 changed files with 86 additions and 52 deletions
|
@ -8,7 +8,7 @@ parameters:
|
||||||
# Ignore errors caused by Template static class reflection
|
# Ignore errors caused by Template static class reflection
|
||||||
- '#Call to an undefined static method Template::[a-zA-Z0-9\\_]+\(\)\.#'
|
- '#Call to an undefined static method Template::[a-zA-Z0-9\\_]+\(\)\.#'
|
||||||
level:
|
level:
|
||||||
8
|
9
|
||||||
paths:
|
paths:
|
||||||
- %rootDir%/../../../lib
|
- %rootDir%/../../../lib
|
||||||
- %rootDir%/../../../www
|
- %rootDir%/../../../www
|
||||||
|
|
|
@ -9,10 +9,11 @@ class Db{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @template T
|
||||||
* @param string $query
|
* @param string $query
|
||||||
* @param array<mixed> $args
|
* @param array<mixed> $args
|
||||||
* @param string $class
|
* @param class-string<T> $class
|
||||||
* @return Array<mixed>
|
* @return Array<T>
|
||||||
*/
|
*/
|
||||||
public static function Query(string $query, array $args = [], string $class = 'stdClass'): array{
|
public static function Query(string $query, array $args = [], string $class = 'stdClass'): array{
|
||||||
return $GLOBALS['DbConnection']->Query($query, $args, $class);
|
return $GLOBALS['DbConnection']->Query($query, $args, $class);
|
||||||
|
|
|
@ -41,21 +41,23 @@ class DbConnection{
|
||||||
$connectionString .= ';dbname=' . $defaultDatabase;
|
$connectionString .= ';dbname=' . $defaultDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We can't use persistent connections (connection pooling) because we would have race condition problems with last_insert_id()
|
||||||
$params = [\PDO::ATTR_EMULATE_PREPARES => false, \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_PERSISTENT => false];
|
$params = [\PDO::ATTR_EMULATE_PREPARES => false, \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_PERSISTENT => false];
|
||||||
|
|
||||||
if($forceUtf8){
|
if($forceUtf8){
|
||||||
$params[\PDO::MYSQL_ATTR_INIT_COMMAND] = 'set names utf8mb4 collate utf8mb4_unicode_ci;';
|
$params[\PDO::MYSQL_ATTR_INIT_COMMAND] = 'set names utf8mb4 collate utf8mb4_unicode_ci;';
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can't use persistent connections (connection pooling) because we would have race condition problems with last_insert_id()
|
|
||||||
$this->_link = new \PDO($connectionString, $user, $password, $params);
|
$this->_link = new \PDO($connectionString, $user, $password, $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Execute a generic query in the database.
|
||||||
|
* @template T
|
||||||
* @param string $sql The SQL query to execute.
|
* @param string $sql The SQL query to execute.
|
||||||
* @param array<mixed> $params An array of parameters to bind to the SQL statement.
|
* @param array<mixed> $params An array of parameters to bind to the SQL statement.
|
||||||
* @param string $class The type of object to return in the return array.
|
* @param class-string<T> $class The type of object to return in the return array.
|
||||||
* @return Array<mixed>
|
* @return Array<T>
|
||||||
* @throws Exceptions\DuplicateDatabaseKeyException When a unique key constraint has been violated.
|
* @throws Exceptions\DuplicateDatabaseKeyException When a unique key constraint has been violated.
|
||||||
* @throws Exceptions\DatabaseQueryException When an error occurs during execution of the query.
|
* @throws Exceptions\DatabaseQueryException When an error occurs during execution of the query.
|
||||||
*/
|
*/
|
||||||
|
@ -131,17 +133,9 @@ class DbConnection{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \PDOException $ex The exception to create details from.
|
* @template T
|
||||||
* @param string $sql The prepared SQL that caused the exception.
|
* @param class-string<T> $class
|
||||||
* @param array<mixed> $params The parameters passed to the prepared SQL.
|
* @return Array<T>
|
||||||
*/
|
|
||||||
private function CreateDetailedException(\PDOException $ex, string $sql, array $params): Exceptions\DatabaseQueryException{
|
|
||||||
// Throw a custom exception that includes more information on the query and paramaters
|
|
||||||
return new Exceptions\DatabaseQueryException('Error when executing query: ' . $ex->getMessage() . '. Query: ' . $sql . '. Parameters: ' . vds($params));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Array<mixed>
|
|
||||||
* @throws \PDOException When an error occurs during execution of the query.
|
* @throws \PDOException When an error occurs during execution of the query.
|
||||||
*/
|
*/
|
||||||
private function ExecuteQuery(\PDOStatement $handle, string $class = 'stdClass'): array{
|
private function ExecuteQuery(\PDOStatement $handle, string $class = 'stdClass'): array{
|
||||||
|
@ -287,4 +281,14 @@ class DbConnection{
|
||||||
|
|
||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \PDOException $ex The exception to create details from.
|
||||||
|
* @param string $sql The prepared SQL that caused the exception.
|
||||||
|
* @param array<mixed> $params The parameters passed to the prepared SQL.
|
||||||
|
*/
|
||||||
|
private function CreateDetailedException(\PDOException $ex, string $sql, array $params): Exceptions\DatabaseQueryException{
|
||||||
|
// Throw a custom exception that includes more information on the query and paramaters
|
||||||
|
return new Exceptions\DatabaseQueryException('Error when executing query: ' . $ex->getMessage() . '. Query: ' . $sql . '. Parameters: ' . vds($params));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ class Ebook{
|
||||||
public string $WwwFilesystemPath;
|
public string $WwwFilesystemPath;
|
||||||
public string $RepoFilesystemPath;
|
public string $RepoFilesystemPath;
|
||||||
public string $Url;
|
public string $Url;
|
||||||
public string $KindleCoverUrl;
|
public ?string $KindleCoverUrl;
|
||||||
public string $EpubUrl;
|
public string $EpubUrl;
|
||||||
public string $AdvancedEpubUrl;
|
public string $AdvancedEpubUrl;
|
||||||
public string $KepubUrl;
|
public string $KepubUrl;
|
||||||
|
@ -68,8 +68,8 @@ class Ebook{
|
||||||
public string $TitleWithCreditsHtml = '';
|
public string $TitleWithCreditsHtml = '';
|
||||||
public DateTimeImmutable $Created;
|
public DateTimeImmutable $Created;
|
||||||
public DateTimeImmutable $Updated;
|
public DateTimeImmutable $Updated;
|
||||||
public string $TextUrl;
|
public ?string $TextUrl;
|
||||||
public string $TextSinglePageUrl;
|
public ?string $TextSinglePageUrl;
|
||||||
public ?string $TextSinglePageSizeNumber = null;
|
public ?string $TextSinglePageSizeNumber = null;
|
||||||
public ?string $TextSinglePageSizeUnit = null;
|
public ?string $TextSinglePageSizeUnit = null;
|
||||||
/** @var ?array<string> $TocEntries */
|
/** @var ?array<string> $TocEntries */
|
||||||
|
|
|
@ -84,18 +84,22 @@ class HttpInput{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var ?string $var */
|
||||||
return $var;
|
return $var;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function Int(HttpVariableSource $set, string $variable): ?int{
|
public static function Int(HttpVariableSource $set, string $variable): ?int{
|
||||||
|
/** @var ?int */
|
||||||
return self::GetHttpVar($variable, HttpVariableType::Integer, $set);
|
return self::GetHttpVar($variable, HttpVariableType::Integer, $set);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function Bool(HttpVariableSource $set, string $variable): ?bool{
|
public static function Bool(HttpVariableSource $set, string $variable): ?bool{
|
||||||
|
/** @var ?bool */
|
||||||
return self::GetHttpVar($variable, HttpVariableType::Boolean, $set);
|
return self::GetHttpVar($variable, HttpVariableType::Boolean, $set);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function Dec(HttpVariableSource $set, string $variable): ?float{
|
public static function Dec(HttpVariableSource $set, string $variable): ?float{
|
||||||
|
/** @var ?float */
|
||||||
return self::GetHttpVar($variable, HttpVariableType::Decimal, $set);
|
return self::GetHttpVar($variable, HttpVariableType::Decimal, $set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +108,13 @@ class HttpInput{
|
||||||
* @return array<string>
|
* @return array<string>
|
||||||
*/
|
*/
|
||||||
public static function Array(HttpVariableSource $set, string $variable): ?array{
|
public static function Array(HttpVariableSource $set, string $variable): ?array{
|
||||||
|
/** @var array<string> */
|
||||||
return self::GetHttpVar($variable, HttpVariableType::Array, $set);
|
return self::GetHttpVar($variable, HttpVariableType::Array, $set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string>|array<int>|array<float>|array<bool>|string|int|float|bool|null
|
||||||
|
*/
|
||||||
private static function GetHttpVar(string $variable, HttpVariableType $type, HttpVariableSource $set): mixed{
|
private static function GetHttpVar(string $variable, HttpVariableType $type, HttpVariableSource $set): mixed{
|
||||||
$vars = [];
|
$vars = [];
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ class Library{
|
||||||
*/
|
*/
|
||||||
public static function GetEbooks(): array{
|
public static function GetEbooks(): array{
|
||||||
// Get all ebooks, unsorted.
|
// Get all ebooks, unsorted.
|
||||||
|
/** @var array<Ebook> */
|
||||||
return self::GetFromApcu('ebooks');
|
return self::GetFromApcu('ebooks');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +122,7 @@ class Library{
|
||||||
* @throws Exceptions\AppException
|
* @throws Exceptions\AppException
|
||||||
*/
|
*/
|
||||||
public static function GetEbooksByAuthor(string $wwwFilesystemPath): array{
|
public static function GetEbooksByAuthor(string $wwwFilesystemPath): array{
|
||||||
|
/** @var array<Ebook> */
|
||||||
return self::GetFromApcu('author-' . $wwwFilesystemPath);
|
return self::GetFromApcu('author-' . $wwwFilesystemPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +131,7 @@ class Library{
|
||||||
*/
|
*/
|
||||||
public static function GetEbooksByTag(string $tag): array{
|
public static function GetEbooksByTag(string $tag): array{
|
||||||
try{
|
try{
|
||||||
|
/** @var array<Ebook> */
|
||||||
return apcu_fetch('tag-' . $tag) ?? [];
|
return apcu_fetch('tag-' . $tag) ?? [];
|
||||||
}
|
}
|
||||||
catch(Safe\Exceptions\ApcuException){
|
catch(Safe\Exceptions\ApcuException){
|
||||||
|
@ -141,6 +144,7 @@ class Library{
|
||||||
* @throws Exceptions\AppException
|
* @throws Exceptions\AppException
|
||||||
*/
|
*/
|
||||||
public static function GetEbookCollections(): array{
|
public static function GetEbookCollections(): array{
|
||||||
|
/** @var array<string, Collection> */
|
||||||
return self::GetFromApcu('collections');
|
return self::GetFromApcu('collections');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +154,7 @@ class Library{
|
||||||
*/
|
*/
|
||||||
public static function GetEbooksByCollection(string $collection): array{
|
public static function GetEbooksByCollection(string $collection): array{
|
||||||
// Do we have the tag's ebooks cached?
|
// Do we have the tag's ebooks cached?
|
||||||
|
/** @var array<Ebook> */
|
||||||
return self::GetFromApcu('collection-' . $collection);
|
return self::GetFromApcu('collection-' . $collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +163,7 @@ class Library{
|
||||||
* @throws Exceptions\AppException
|
* @throws Exceptions\AppException
|
||||||
*/
|
*/
|
||||||
public static function GetTags(): array{
|
public static function GetTags(): array{
|
||||||
|
/** @var array<Tag> */
|
||||||
return self::GetFromApcu('tags');
|
return self::GetFromApcu('tags');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,7 +544,7 @@ class Library{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, array<int|string, array<int|string, mixed>>>
|
* @return array<string, array<int|string, array<int|string, stdClass>>>
|
||||||
* @throws Exceptions\AppException
|
* @throws Exceptions\AppException
|
||||||
*/
|
*/
|
||||||
public static function RebuildBulkDownloadsCache(): array{
|
public static function RebuildBulkDownloadsCache(): array{
|
||||||
|
@ -662,6 +668,7 @@ class Library{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var array<Ebook> $result */
|
||||||
$result = self::GetFromApcu('ebook-' . $ebookWwwFilesystemPath);
|
$result = self::GetFromApcu('ebook-' . $ebookWwwFilesystemPath);
|
||||||
|
|
||||||
if(sizeof($result) > 0){
|
if(sizeof($result) > 0){
|
||||||
|
|
|
@ -25,7 +25,7 @@ class Template{
|
||||||
* @param array<mixed> $arguments
|
* @param array<mixed> $arguments
|
||||||
*/
|
*/
|
||||||
public static function __callStatic(string $function, array $arguments): string{
|
public static function __callStatic(string $function, array $arguments): string{
|
||||||
if(isset($arguments[0])){
|
if(isset($arguments[0]) && is_array($arguments[0])){
|
||||||
return self::Get($function, $arguments[0]);
|
return self::Get($function, $arguments[0]);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
|
@ -16,10 +16,12 @@ if($GLOBALS['User'] !== null && $GLOBALS['User']->Benefits->CanBulkDownload){
|
||||||
$collection = [];
|
$collection = [];
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
/** @var array<string, array<string, stdClass>> $collection */
|
||||||
$collection = apcu_fetch('bulk-downloads-' . $class);
|
$collection = apcu_fetch('bulk-downloads-' . $class);
|
||||||
}
|
}
|
||||||
catch(Safe\Exceptions\ApcuException){
|
catch(Safe\Exceptions\ApcuException){
|
||||||
$result = Library::RebuildBulkDownloadsCache();
|
$result = Library::RebuildBulkDownloadsCache();
|
||||||
|
/** @var array<string, array<string, stdClass>> $collection */
|
||||||
$collection = $result[$class];
|
$collection = $result[$class];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,13 @@ try{
|
||||||
|
|
||||||
// Get all collections and then find the specific one we're looking for
|
// Get all collections and then find the specific one we're looking for
|
||||||
try{
|
try{
|
||||||
|
/** @var array<stdClass> $collections */
|
||||||
$collections = apcu_fetch('bulk-downloads-collections');
|
$collections = apcu_fetch('bulk-downloads-collections');
|
||||||
}
|
}
|
||||||
catch(Safe\Exceptions\ApcuException){
|
catch(Safe\Exceptions\ApcuException){
|
||||||
$result = Library::RebuildBulkDownloadsCache();
|
$result = Library::RebuildBulkDownloadsCache();
|
||||||
|
|
||||||
|
/** @var array<stdClass> $collections */
|
||||||
$collections = $result['collections'];
|
$collections = $result['collections'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,10 +44,13 @@ try{
|
||||||
|
|
||||||
// Get all authors and then find the specific one we're looking for
|
// Get all authors and then find the specific one we're looking for
|
||||||
try{
|
try{
|
||||||
|
/** @var array<stdClass> $collections */
|
||||||
$collections = apcu_fetch('bulk-downloads-authors');
|
$collections = apcu_fetch('bulk-downloads-authors');
|
||||||
}
|
}
|
||||||
catch(Safe\Exceptions\ApcuException){
|
catch(Safe\Exceptions\ApcuException){
|
||||||
$result = Library::RebuildBulkDownloadsCache();
|
$result = Library::RebuildBulkDownloadsCache();
|
||||||
|
|
||||||
|
/** @var array<stdClass> $collections */
|
||||||
$collections = $result['authors'];
|
$collections = $result['authors'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +76,7 @@ catch(Exceptions\CollectionNotFoundException){
|
||||||
?><?= Template::Header(['title' => 'Download ', 'highlight' => '', 'description' => 'Download zip files containing all of the Standard Ebooks released in a given month.']) ?>
|
?><?= Template::Header(['title' => 'Download ', 'highlight' => '', 'description' => 'Download zip files containing all of the Standard Ebooks released in a given month.']) ?>
|
||||||
<main>
|
<main>
|
||||||
<section class="bulk-downloads">
|
<section class="bulk-downloads">
|
||||||
<h1>Download the <?= $collection->Label ?> Collection</h1>
|
<h1>Download the <?= $collection?->Label ?> Collection</h1>
|
||||||
<? if($canDownload){ ?>
|
<? if($canDownload){ ?>
|
||||||
<p>Select the ebook format in which you’d like to download this collection.</p>
|
<p>Select the ebook format in which you’d like to download this collection.</p>
|
||||||
<p>You can also read about <a href="/help/how-to-use-our-ebooks#which-file-to-download">which ebook format to download</a>.</p>
|
<p>You can also read about <a href="/help/how-to-use-our-ebooks#which-file-to-download">which ebook format to download</a>.</p>
|
||||||
|
|
|
@ -16,16 +16,13 @@ try{
|
||||||
|
|
||||||
// Do we have the ebook cached?
|
// Do we have the ebook cached?
|
||||||
try{
|
try{
|
||||||
|
/** @var Ebook $ebook */
|
||||||
$ebook = apcu_fetch('ebook-' . $wwwFilesystemPath);
|
$ebook = apcu_fetch('ebook-' . $wwwFilesystemPath);
|
||||||
}
|
}
|
||||||
catch(Safe\Exceptions\ApcuException){
|
catch(Safe\Exceptions\ApcuException){
|
||||||
$ebook = new Ebook($wwwFilesystemPath);
|
$ebook = new Ebook($wwwFilesystemPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($ebook === null){
|
|
||||||
throw new Exceptions\InvalidFileException();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($format){
|
switch($format){
|
||||||
case EbookFormat::Kepub:
|
case EbookFormat::Kepub:
|
||||||
$downloadUrl = $ebook->KepubUrl;
|
$downloadUrl = $ebook->KepubUrl;
|
||||||
|
|
|
@ -28,6 +28,7 @@ try{
|
||||||
// https://standardebooks.org/ebooks/omar-khayyam/the-rubaiyat-of-omar-khayyam/edward-fitzgerald/edmund-dulac
|
// https://standardebooks.org/ebooks/omar-khayyam/the-rubaiyat-of-omar-khayyam/edward-fitzgerald/edmund-dulac
|
||||||
// We can tell because if so, the dir we are passed will exist, but there will be no 'src' folder.
|
// 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')){
|
if(is_dir($wwwFilesystemPath) && !is_dir($wwwFilesystemPath . '/src')){
|
||||||
|
/** @var DirectoryIterator $file */
|
||||||
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($wwwFilesystemPath)) as $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.
|
// 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.
|
// 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.
|
||||||
|
@ -39,6 +40,7 @@ try{
|
||||||
|
|
||||||
// Do we have the ebook cached?
|
// Do we have the ebook cached?
|
||||||
try{
|
try{
|
||||||
|
/** @var Ebook $ebook */
|
||||||
$ebook = apcu_fetch('ebook-' . $wwwFilesystemPath);
|
$ebook = apcu_fetch('ebook-' . $wwwFilesystemPath);
|
||||||
}
|
}
|
||||||
catch(Safe\Exceptions\ApcuException){
|
catch(Safe\Exceptions\ApcuException){
|
||||||
|
@ -211,7 +213,7 @@ catch(Exceptions\EbookNotFoundException){
|
||||||
<p class="us-pd-warning">This ebook is thought to be free of copyright restrictions in the United States. It may still be under copyright in other countries. If you’re not located in the United States, you must check your local laws to verify that this ebook is free of copyright restrictions in the country you’re located in before accessing, downloading, or using it.</p>
|
<p class="us-pd-warning">This ebook is thought to be free of copyright restrictions in the United States. It may still be under copyright in other countries. If you’re not located in the United States, you must check your local laws to verify that this ebook is free of copyright restrictions in the country you’re located in before accessing, downloading, or using it.</p>
|
||||||
|
|
||||||
<div class="downloads-container">
|
<div class="downloads-container">
|
||||||
<figure class="<? if($ebook->WordCount < 100000){ ?>small<? }elseif($ebook->WordCount >= 100000 && $ebook->WordCount < 200000){ ?>medium<? }elseif($ebook->WordCount >= 200000 && $ebook->WordCount <= 300000){ ?>large<? }elseif($ebook->WordCount >= 300000 && $ebook->WordCount < 400000){ ?>xlarge<? }elseif($ebook->WordCount >= 400000){ ?>xxlarge<? } ?>">
|
<figure class="<? if($ebook->WordCount < 100000){ ?>small<? }elseif($ebook->WordCount < 200000){ ?>medium<? }elseif($ebook->WordCount <= 300000){ ?>large<? }elseif($ebook->WordCount < 400000){ ?>xlarge<? }else{ ?>xxlarge<? } ?>">
|
||||||
<picture>
|
<picture>
|
||||||
<source srcset="<?= $ebook->CoverImage2xAvifUrl ?> 2x, <?= $ebook->CoverImageAvifUrl ?> 1x" type="image/avif"/>
|
<source srcset="<?= $ebook->CoverImage2xAvifUrl ?> 2x, <?= $ebook->CoverImageAvifUrl ?> 1x" type="image/avif"/>
|
||||||
<source srcset="<?= $ebook->CoverImage2xUrl ?> 2x, <?= $ebook->CoverImageUrl ?> 1x" type="image/jpg"/>
|
<source srcset="<?= $ebook->CoverImage2xUrl ?> 2x, <?= $ebook->CoverImageUrl ?> 1x" type="image/jpg"/>
|
||||||
|
|
|
@ -23,9 +23,11 @@ if($type === 'atom'){
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
/** @var array<stdClass> $feeds */
|
||||||
$feeds = apcu_fetch('feeds-index-' . $type . '-' . $class);
|
$feeds = apcu_fetch('feeds-index-' . $type . '-' . $class);
|
||||||
}
|
}
|
||||||
catch(Safe\Exceptions\ApcuException){
|
catch(Safe\Exceptions\ApcuException){
|
||||||
|
/** @var array<stdClass> $feeds */
|
||||||
$feeds = Library::RebuildFeedsCache($type, $class);
|
$feeds = Library::RebuildFeedsCache($type, $class);
|
||||||
}
|
}
|
||||||
?><?= Template::Header(['title' => $ucType . ' Ebook Feeds by ' . $ucTitle, 'description' => 'A list of available ' . $ucType . ' feeds of Standard Ebooks ebooks by ' . $lcTitle . '.']) ?>
|
?><?= Template::Header(['title' => $ucType . ' Ebook Feeds by ' . $ucTitle, 'description' => 'A list of available ' . $ucType . ' feeds of Standard Ebooks ebooks by ' . $lcTitle . '.']) ?>
|
||||||
|
|
|
@ -35,6 +35,7 @@ try{
|
||||||
throw new Exceptions\WebhookException('Couldn\'t understand HTTP request.', $post);
|
throw new Exceptions\WebhookException('Couldn\'t understand HTTP request.', $post);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var array<array<string>> $data */
|
||||||
$data = json_decode($post, true);
|
$data = json_decode($post, true);
|
||||||
|
|
||||||
// Decide what event we just received.
|
// Decide what event we just received.
|
||||||
|
|
|
@ -21,13 +21,16 @@ try{
|
||||||
throw new Exceptions\InvalidCredentialsException();
|
throw new Exceptions\InvalidCredentialsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$post = json_decode(file_get_contents('php://input'));
|
$post = file_get_contents('php://input');
|
||||||
|
|
||||||
if(!$post || !property_exists($post, 'RecordType')){
|
/** @var stdClass $data */
|
||||||
|
$data = json_decode($post);
|
||||||
|
|
||||||
|
if(!property_exists($data, 'RecordType')){
|
||||||
throw new Exceptions\WebhookException('Couldn\'t understand HTTP request.', $post);
|
throw new Exceptions\WebhookException('Couldn\'t understand HTTP request.', $post);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($post->RecordType == 'SpamComplaint'){
|
if($data->RecordType == 'SpamComplaint'){
|
||||||
// Received when a user marks an email as spam
|
// Received when a user marks an email as spam
|
||||||
$log->Write('Event type: spam complaint.');
|
$log->Write('Event type: spam complaint.');
|
||||||
|
|
||||||
|
@ -36,13 +39,13 @@ try{
|
||||||
from NewsletterSubscriptions ns
|
from NewsletterSubscriptions ns
|
||||||
inner join Users u using(UserId)
|
inner join Users u using(UserId)
|
||||||
where u.Email = ?
|
where u.Email = ?
|
||||||
', [$post->Email]);
|
', [$data->Email]);
|
||||||
}
|
}
|
||||||
elseif($post->RecordType == 'SubscriptionChange' && $post->SuppressSending){
|
elseif($data->RecordType == 'SubscriptionChange' && $data->SuppressSending){
|
||||||
// Received when a user clicks Postmark's "Unsubscribe" link in a newsletter email
|
// Received when a user clicks Postmark's "Unsubscribe" link in a newsletter email
|
||||||
$log->Write('Event type: unsubscribe.');
|
$log->Write('Event type: unsubscribe.');
|
||||||
|
|
||||||
$email = $post->Recipient;
|
$email = $data->Recipient;
|
||||||
|
|
||||||
// Remove the email from our newsletter list
|
// Remove the email from our newsletter list
|
||||||
Db::Query('
|
Db::Query('
|
||||||
|
@ -54,18 +57,18 @@ try{
|
||||||
|
|
||||||
// Remove the suppression from Postmark, since we deleted it from our own list we will never email them again anyway
|
// Remove the suppression from Postmark, since we deleted it from our own list we will never email them again anyway
|
||||||
$handle = curl_init();
|
$handle = curl_init();
|
||||||
curl_setopt($handle, CURLOPT_URL, 'https://api.postmarkapp.com/message-streams/' . $post->MessageStream . '/suppressions/delete');
|
curl_setopt($handle, CURLOPT_URL, 'https://api.postmarkapp.com/message-streams/' . $data->MessageStream . '/suppressions/delete');
|
||||||
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
|
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
|
||||||
curl_setopt($handle, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Accept: application/json', 'X-Postmark-Server-Token: ' . $smtpUsername]);
|
curl_setopt($handle, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Accept: application/json', 'X-Postmark-Server-Token: ' . $smtpUsername]);
|
||||||
curl_setopt($handle, CURLOPT_CUSTOMREQUEST, "POST");
|
curl_setopt($handle, CURLOPT_CUSTOMREQUEST, "POST");
|
||||||
curl_setopt($handle, CURLOPT_POSTFIELDS, '{"Suppressions": [{"EmailAddress": "' . $email . '"}]}');
|
curl_setopt($handle, CURLOPT_POSTFIELDS, '{"Suppressions": [{"EmailAddress": "' . $email . '"}]}');
|
||||||
curl_exec($handle);
|
curl_exec($handle);
|
||||||
}
|
}
|
||||||
elseif($post->RecordType == 'SubscriptionChange' && $post->SuppressionReason === null){
|
elseif($data->RecordType == 'SubscriptionChange' && $data->SuppressionReason === null){
|
||||||
$log->Write('Event type: suppression deletion.');
|
$log->Write('Event type: suppression deletion.');
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
$log->Write('Unrecognized event: ' . $post->RecordType);
|
$log->Write('Unrecognized event: ' . $data->RecordType);
|
||||||
}
|
}
|
||||||
|
|
||||||
$log->Write('Event processed.');
|
$log->Write('Event processed.');
|
||||||
|
|
|
@ -23,6 +23,7 @@ try{
|
||||||
throw new Exceptions\InvalidCredentialsException();
|
throw new Exceptions\InvalidCredentialsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var stdClass $data */
|
||||||
$data = json_decode($post);
|
$data = json_decode($post);
|
||||||
|
|
||||||
if($data->fromAddress == 'support@fracturedatlas.org' && strpos($data->subject, 'NOTICE:') !== false){
|
if($data->fromAddress == 'support@fracturedatlas.org' && strpos($data->subject, 'NOTICE:') !== false){
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue