More type fixes

This commit is contained in:
Alex Cabal 2025-02-26 15:11:36 -06:00
parent a5a19f947f
commit 99b5fd66f2
17 changed files with 103 additions and 122 deletions

26
composer.lock generated
View file

@ -8,16 +8,16 @@
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
"version": "0.12.1", "version": "0.12.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/brick/math.git", "url": "https://github.com/brick/math.git",
"reference": "f510c0a40911935b77b86859eb5223d58d660df1" "reference": "901eddb1e45a8e0f689302e40af871c181ecbe40"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", "url": "https://api.github.com/repos/brick/math/zipball/901eddb1e45a8e0f689302e40af871c181ecbe40",
"reference": "f510c0a40911935b77b86859eb5223d58d660df1", "reference": "901eddb1e45a8e0f689302e40af871c181ecbe40",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -26,7 +26,7 @@
"require-dev": { "require-dev": {
"php-coveralls/php-coveralls": "^2.2", "php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^10.1", "phpunit/phpunit": "^10.1",
"vimeo/psalm": "5.16.0" "vimeo/psalm": "6.8.8"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -56,7 +56,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/brick/math/issues", "issues": "https://github.com/brick/math/issues",
"source": "https://github.com/brick/math/tree/0.12.1" "source": "https://github.com/brick/math/tree/0.12.2"
}, },
"funding": [ "funding": [
{ {
@ -64,7 +64,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-11-29T23:19:16+00:00" "time": "2025-02-26T10:21:45+00:00"
}, },
{ {
"name": "erusev/parsedown", "name": "erusev/parsedown",
@ -694,16 +694,16 @@
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v6.4.15", "version": "v6.4.19",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "3cb242f059c14ae08591c5c4087d1fe443564392" "reference": "7a1c12e87b08ec9c97abdd188c9b3f5a40e37fc3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/3cb242f059c14ae08591c5c4087d1fe443564392", "url": "https://api.github.com/repos/symfony/process/zipball/7a1c12e87b08ec9c97abdd188c9b3f5a40e37fc3",
"reference": "3cb242f059c14ae08591c5c4087d1fe443564392", "reference": "7a1c12e87b08ec9c97abdd188c9b3f5a40e37fc3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -735,7 +735,7 @@
"description": "Executes commands in sub-processes", "description": "Executes commands in sub-processes",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/process/tree/v6.4.15" "source": "https://github.com/symfony/process/tree/v6.4.19"
}, },
"funding": [ "funding": [
{ {
@ -751,7 +751,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-06T14:19:14+00:00" "time": "2025-02-04T13:35:48+00:00"
}, },
{ {
"name": "thecodingmachine/safe", "name": "thecodingmachine/safe",

View file

@ -33,6 +33,8 @@ parameters:
- Emit404 - Emit404
- RedirectToLogin - RedirectToLogin
exceptions: exceptions:
# PHPStan only uses PHPDocs to compute exception bubbling; without this line, PHPStan assumes that any function without a `@throws` doc throws any number of exceptions, instead of no exceptions.
implicitThrows: false
check: check:
missingCheckedExceptionInThrows: true missingCheckedExceptionInThrows: true
tooWideThrowType: true tooWideThrowType: true

View file

@ -676,16 +676,16 @@ class Artwork{
* @throws Exceptions\InvalidImageUploadException * @throws Exceptions\InvalidImageUploadException
*/ */
private function WriteImageAndThumbnails(string $imagePath): void{ private function WriteImageAndThumbnails(string $imagePath): void{
try{
exec('exiftool -quiet -overwrite_original -all= ' . escapeshellarg($imagePath)); exec('exiftool -quiet -overwrite_original -all= ' . escapeshellarg($imagePath));
copy($imagePath, $this->ImageFsPath); copy($imagePath, $this->ImageFsPath);
// Generate the thumbnails // Generate the thumbnails
try{
$image = new Image($imagePath); $image = new Image($imagePath);
$image->Resize($this->ThumbFsPath, ARTWORK_THUMBNAIL_WIDTH, ARTWORK_THUMBNAIL_HEIGHT); $image->Resize($this->ThumbFsPath, ARTWORK_THUMBNAIL_WIDTH, ARTWORK_THUMBNAIL_HEIGHT);
$image->Resize($this->Thumb2xFsPath, ARTWORK_THUMBNAIL_WIDTH * 2, ARTWORK_THUMBNAIL_HEIGHT * 2); $image->Resize($this->Thumb2xFsPath, ARTWORK_THUMBNAIL_WIDTH * 2, ARTWORK_THUMBNAIL_HEIGHT * 2);
} }
catch(\Safe\Exceptions\FilesystemException | \Safe\Exceptions\ImageException){ catch(\Safe\Exceptions\ExecException | \Safe\Exceptions\FilesystemException){
throw new Exceptions\InvalidImageUploadException('Failed to generate thumbnail.'); throw new Exceptions\InvalidImageUploadException('Failed to generate thumbnail.');
} }
} }

View file

@ -321,6 +321,7 @@ class Db{
*/ */
protected static function PreparePdoHandle(string $sql, array $params): \PDOStatement{ protected static function PreparePdoHandle(string $sql, array $params): \PDOStatement{
try{ try{
/** @throws \PDOException */
$handle = static::$Link->prepare($sql); $handle = static::$Link->prepare($sql);
} }
catch(\PDOException $ex){ catch(\PDOException $ex){

View file

@ -23,7 +23,12 @@ enum ImageMimeType: string{
return null; return null;
} }
try{
$mimeType = mime_content_type($path); $mimeType = mime_content_type($path);
}
catch(\Safe\Exceptions\FileinfoException){
return null;
}
$mimeType = match($mimeType){ $mimeType = match($mimeType){
'image/x-ms-bmp', 'image/x-bmp' => 'image/bmp', 'image/x-ms-bmp', 'image/x-bmp' => 'image/bmp',

View file

@ -317,13 +317,8 @@ class HttpInput{
case Enums\HttpVariableType::Integer: case Enums\HttpVariableType::Integer:
// Can't use `ctype_digit()` because we may want negative integers. // Can't use `ctype_digit()` because we may want negative integers.
if(is_numeric($var) && mb_strpos((string)$var, '.') === false){ if(is_numeric($var) && mb_strpos((string)$var, '.') === false){
try{
return intval($var); return intval($var);
} }
catch(Exception){
return null;
}
}
break; break;
case Enums\HttpVariableType::Boolean: case Enums\HttpVariableType::Boolean:
if($var === false || (is_string($var) && ($var === '0' || strtolower($var) == 'false' || strtolower($var) == 'off'))){ if($var === false || (is_string($var) && ($var === '0' || strtolower($var) == 'false' || strtolower($var) == 'off'))){
@ -334,13 +329,8 @@ class HttpInput{
} }
case Enums\HttpVariableType::Decimal: case Enums\HttpVariableType::Decimal:
if(is_numeric($var)){ if(is_numeric($var)){
try{
return floatval($var); return floatval($var);
} }
catch(Exception){
return null;
}
}
break; break;
case Enums\HttpVariableType::DateTime: case Enums\HttpVariableType::DateTime:
if(is_string($var) && $var != ''){ if(is_string($var) && $var != ''){

View file

@ -18,10 +18,11 @@ class Image{
/** /**
* @return \GdImage * @return \GdImage
* @throws \Safe\Exceptions\ImageException *
* @throws Exceptions\InvalidImageUploadException * @throws Exceptions\InvalidImageUploadException
*/ */
private function GetImageHandle(){ private function GetImageHandle(){
try{
switch($this->MimeType){ switch($this->MimeType){
case Enums\ImageMimeType::JPG: case Enums\ImageMimeType::JPG:
$handle = \Safe\imagecreatefromjpeg($this->Path); $handle = \Safe\imagecreatefromjpeg($this->Path);
@ -38,6 +39,10 @@ class Image{
default: default:
throw new \Exceptions\InvalidImageUploadException(); throw new \Exceptions\InvalidImageUploadException();
} }
}
catch(\Safe\Exceptions\ImageException){
throw new \Exceptions\InvalidImageUploadException();
}
return $handle; return $handle;
} }
@ -93,31 +98,22 @@ class Image{
public function Resize(string $destImagePath, int $width, int $height): void{ public function Resize(string $destImagePath, int $width, int $height): void{
try{ try{
$imageDimensions = getimagesize($this->Path); $imageDimensions = getimagesize($this->Path);
}
catch(\Safe\Exceptions\ImageException $ex){
throw new Exceptions\InvalidImageUploadException($ex->getMessage());
}
$imageWidth = $imageDimensions[0] ?? 0; $imageWidth = $imageDimensions[0] ?? 0;
$imageHeight = $imageDimensions[1] ?? 0; $imageHeight = $imageDimensions[1] ?? 0;
if($imageHeight > $imageWidth){ if($imageHeight > $imageWidth){
$destinationHeight = $height; $destinationHeight = $height;
try{
$destinationWidth = intval($destinationHeight * ($imageWidth / $imageHeight)); $destinationWidth = intval($destinationHeight * ($imageWidth / $imageHeight));
} }
catch(\DivisionByZeroError){
$destinationWidth = 0;
}
}
else{ else{
$destinationWidth = $width; $destinationWidth = $width;
try{ if($imageWidth == 0){
$destinationHeight = intval($destinationWidth * ($imageHeight / $imageWidth));
}
catch(\DivisionByZeroError){
$destinationHeight = 0; $destinationHeight = 0;
} }
else{
$destinationHeight = intval($destinationWidth * ($imageHeight / $imageWidth));
}
} }
$srcImageHandle = $this->GetImageHandle(); $srcImageHandle = $this->GetImageHandle();
@ -127,4 +123,8 @@ class Image{
imagejpeg($thumbImageHandle, $destImagePath); imagejpeg($thumbImageHandle, $destImagePath);
} }
catch(\Safe\Exceptions\ImageException $ex){
throw new Exceptions\InvalidImageUploadException($ex->getMessage());
}
}
} }

View file

@ -60,6 +60,10 @@ class PollVote{
} }
else{ else{
try{ try{
/**
* @throws Exceptions\PollItemNotFoundException
* @throws Exceptions\PollNotFoundException
*/
if(!$this->PollItem->Poll->IsActive()){ if(!$this->PollItem->Poll->IsActive()){
$error->Add(new Exceptions\PollClosedException()); $error->Add(new Exceptions\PollClosedException());
} }

View file

@ -126,6 +126,7 @@ trait Accessor{
if(property_exists($this, $privateVar)){ if(property_exists($this, $privateVar)){
try{ try{
/** @throws \Throwable */
$this->__get($var); $this->__get($var);
} }
catch(\Throwable){ catch(\Throwable){

View file

@ -7,7 +7,7 @@ namespace Traits;
trait FromRow{ trait FromRow{
/** /**
* Fill an object with the given database row. * Fill an object with the given database row.
* This is useful when a subclass has to fill its object in a `FromRow()` method, but its parent class also has a `FromRow()` method defined. For example, `CompoundAction` and `Action`. * This is useful when a subclass has to fill its object in a `FromRow()` method, but its parent class also has a `FromRow()` method defined.
* *
* @template T of self * @template T of self
* *

View file

@ -224,5 +224,7 @@ catch(Exception $ex){
throw $ex; throw $ex;
} }
finally{ finally{
// `$driver` may be unintialized if we ctrl + c during Selenium initialization.
/** @phpstan-ignore nullsafe.neverNull */
$driver?->quit(); $driver?->quit();
} }

View file

@ -325,5 +325,7 @@ catch(Exception $ex){
throw $ex; throw $ex;
} }
finally{ finally{
// `$driver` may be unintialized if we ctrl + c during Selenium initialization.
/** @phpstan-ignore nullsafe.neverNull */
$driver?->quit(); $driver?->quit();
} }

View file

@ -134,12 +134,6 @@ catch(Exceptions\PageOutOfBoundsException){
header('Location: ' . $url); header('Location: ' . $url);
exit(); exit();
} }
catch(Exceptions\AppException $ex){
// Something very unexpected happened, log and emit 500.
http_response_code(Enums\HttpCode::InternalServerError->value); // Internal server error.
Log::WriteErrorLogEntry($ex);
exit();
}
?><?= Template::Header(['title' => $pageTitle, 'highlight' => 'ebooks', 'description' => $pageDescription, 'canonicalUrl' => $canonicalUrl]) ?> ?><?= Template::Header(['title' => $pageTitle, 'highlight' => 'ebooks', 'description' => $pageDescription, 'canonicalUrl' => $canonicalUrl]) ?>
<main class="ebooks"> <main class="ebooks">
<h1><?= $pageHeader ?></h1> <h1><?= $pageHeader ?></h1>

View file

@ -1,20 +1,13 @@
<? <?
$ebooks = []; $ebooks = [];
$query = HttpInput::Str(GET, 'query') ?? '';
$startPage = HttpInput::Int(GET, 'page') ?? 1;
$count = HttpInput::Int(GET, 'per-page') ?? EBOOKS_PER_PAGE;
try{ if($query !== ''){
$query = HttpInput::Str(GET, 'query') ?? '';
$startPage = HttpInput::Int(GET, 'page') ?? 1;
$count = HttpInput::Int(GET, 'per-page') ?? EBOOKS_PER_PAGE;
if($query !== ''){
$ebooks = Ebook::GetAllByFilter($query, [], Enums\EbookSortType::Newest, $startPage, $count, Enums\EbookReleaseStatusFilter::Released)['ebooks']; $ebooks = Ebook::GetAllByFilter($query, [], Enums\EbookSortType::Newest, $startPage, $count, Enums\EbookReleaseStatusFilter::Released)['ebooks'];
}
}
catch(\Exception){
http_response_code(Enums\HttpCode::InternalServerError->value);
include(WEB_ROOT . '/404.php');
exit();
} }
print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"" . SITE_URL . "/feeds/atom/style\" type=\"text/xsl\"?>\n"); print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"" . SITE_URL . "/feeds/atom/style\" type=\"text/xsl\"?>\n");
?> ?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"> <feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">

View file

@ -1,19 +1,13 @@
<? <?
$ebooks = []; $ebooks = [];
$query = HttpInput::Str(GET, 'query') ?? '';
$startPage = HttpInput::Int(GET, 'page') ?? 1;
$count = HttpInput::Int(GET, 'per-page') ?? EBOOKS_PER_PAGE;
try{ if($query !== ''){
$query = HttpInput::Str(GET, 'query') ?? '';
$startPage = HttpInput::Int(GET, 'page') ?? 1;
$count = HttpInput::Int(GET, 'per-page') ?? EBOOKS_PER_PAGE;
if($query !== ''){
$ebooks = Ebook::GetAllByFilter($query, [], Enums\EbookSortType::Newest, $startPage, $count, Enums\EbookReleaseStatusFilter::Released)['ebooks']; $ebooks = Ebook::GetAllByFilter($query, [], Enums\EbookSortType::Newest, $startPage, $count, Enums\EbookReleaseStatusFilter::Released)['ebooks'];
}
}
catch(\Exception){
http_response_code(Enums\HttpCode::InternalServerError->value);
exit();
} }
print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"". SITE_URL . "/feeds/opds/style\" type=\"text/xsl\"?>\n"); print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"". SITE_URL . "/feeds/opds/style\" type=\"text/xsl\"?>\n");
?> ?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:schema="http://schema.org/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"> <feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:schema="http://schema.org/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">

View file

@ -1,20 +1,13 @@
<? <?
$ebooks = []; $ebooks = [];
$query = HttpInput::Str(GET, 'query') ?? '';
$startPage = HttpInput::Int(GET, 'page') ?? 1;
$count = HttpInput::Int(GET, 'per-page') ?? EBOOKS_PER_PAGE;
try{ if($query !== ''){
$query = HttpInput::Str(GET, 'query') ?? '';
$startPage = HttpInput::Int(GET, 'page') ?? 1;
$count = HttpInput::Int(GET, 'per-page') ?? EBOOKS_PER_PAGE;
if($query !== ''){
$ebooks = Ebook::GetAllByFilter($query, [], Enums\EbookSortType::Newest, $startPage, $count, Enums\EbookReleaseStatusFilter::Released)['ebooks']; $ebooks = Ebook::GetAllByFilter($query, [], Enums\EbookSortType::Newest, $startPage, $count, Enums\EbookReleaseStatusFilter::Released)['ebooks'];
}
}
catch(\Exception){
http_response_code(Enums\HttpCode::InternalServerError->value);
include(WEB_ROOT . '/404.php');
exit();
} }
print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"" . SITE_URL . "/feeds/rss/style\" type=\"text/xsl\"?>\n"); print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"" . SITE_URL . "/feeds/rss/style\" type=\"text/xsl\"?>\n");
?> ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">

View file

@ -118,7 +118,7 @@ catch(Exceptions\LoginRequiredException){
catch(Exceptions\InvalidPermissionsException){ catch(Exceptions\InvalidPermissionsException){
Template::ExitWithCode(Enums\HttpCode::Forbidden); Template::ExitWithCode(Enums\HttpCode::Forbidden);
} }
catch(Exceptions\InvalidProjectException | Exceptions\InvalidEbookException | Exceptions\ProjectExistsException | Exceptions\EbookExistsException | Exceptions\EbookIsNotAPlaceholderException $ex){ catch(Exceptions\InvalidProjectException | Exceptions\InvalidEbookException | Exceptions\ProjectExistsException | Exceptions\EbookIsNotAPlaceholderException $ex){
$_SESSION['project'] = $project; $_SESSION['project'] = $project;
$_SESSION['exception'] = $ex; $_SESSION['exception'] = $ex;