Add type hints and some other tweaks to satisfy PHPStan

This commit is contained in:
Alex Cabal 2020-03-01 10:49:32 -06:00
parent caa623bd0b
commit bef5aea7ad
11 changed files with 72 additions and 28 deletions

View file

@ -7,6 +7,9 @@ parameters:
ignoreErrors: ignoreErrors:
# 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\\_]+\(\)\.#'
# Ignore errors caused by no type hints on class properties, as that's not available till PHP 7.4
- '#Property .+? has no typehint specified.#'
level: level:
7 7
paths: paths:

View file

@ -11,7 +11,7 @@ mb_http_output('UTF-8');
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
// Custom error handler to output more details about the specific Apache request that caused an exception. // Custom error handler to output more details about the specific Apache request that caused an exception.
set_exception_handler(function($ex){ set_exception_handler(function(Throwable $ex): void{
$errorString = "----------------------------------------\n"; $errorString = "----------------------------------------\n";
$errorString .= trim(vds(array_intersect_key($_SERVER, array('REQUEST_URI' => '', 'QUERY_STRING' => '', 'REQUEST_METHOD' => '', 'REDIRECT_QUERY_STRING' => '', 'REDIRECT_URL' => '', 'SCRIPT_FILENAME' => '', 'REMOTE_ADDR' => '', 'HTTP_COOKIE' => '', 'HTTP_USER_AGENT' => '', 'SCRIPT_URI' => '')))); $errorString .= trim(vds(array_intersect_key($_SERVER, array('REQUEST_URI' => '', 'QUERY_STRING' => '', 'REQUEST_METHOD' => '', 'REDIRECT_QUERY_STRING' => '', 'REDIRECT_URL' => '', 'SCRIPT_FILENAME' => '', 'REMOTE_ADDR' => '', 'HTTP_COOKIE' => '', 'HTTP_USER_AGENT' => '', 'SCRIPT_URI' => ''))));

View file

@ -5,21 +5,24 @@
use function Safe\ob_end_clean; use function Safe\ob_end_clean;
// Convenience alias of var_dump. // Convenience alias of var_dump.
function vd($var){ function vd($var): void{
var_dump($var); var_dump($var);
} }
// var_dump($var) then die(). // var_dump($var) then die().
function vdd($var){ function vdd($var): void{
var_dump($var); var_dump($var);
die(); die();
} }
// var_dump into a string. // var_dump into a string.
function vds($var){ function vds($var): string{
ob_start(); ob_start();
var_dump($var); var_dump($var);
$str = ob_get_contents(); $str = ob_get_contents();
if($str === false){
$str = '';
}
ob_end_clean(); ob_end_clean();
return $str; return $str;
} }

View file

@ -1,10 +1,11 @@
<? <?
use function Safe\preg_replace; use Safe\DateTime;
use function Safe\file_get_contents; use function Safe\file_get_contents;
use function Safe\preg_match;
use function Safe\glob;
use function Safe\substr;
use function Safe\json_encode; use function Safe\json_encode;
use function Safe\glob;
use function Safe\preg_match;
use function Safe\preg_replace;
use function Safe\substr;
class Ebook{ class Ebook{
public $WwwFilesystemPath; public $WwwFilesystemPath;
@ -153,7 +154,10 @@ class Ebook{
$this->FullTitle = $this->NullIfEmpty($xml->xpath('/package/metadata/dc:title[@id="fulltitle"]')); $this->FullTitle = $this->NullIfEmpty($xml->xpath('/package/metadata/dc:title[@id="fulltitle"]'));
$this->Timestamp = new \DateTime((string)$xml->xpath('/package/metadata/dc:date')[0]); $date = $xml->xpath('/package/metadata/dc:date');
if($date !== false && sizeof($date) > 0){
$this->Timestamp = new DateTime((string)$date[0]);
}
// Get SE tags // Get SE tags
foreach($xml->xpath('/package/metadata/meta[@property="se:subject"]') ?: [] as $tag){ foreach($xml->xpath('/package/metadata/meta[@property="se:subject"]') ?: [] as $tag){
@ -170,14 +174,22 @@ class Ebook{
$this->LocTags[] = (string)$tag; $this->LocTags[] = (string)$tag;
} }
// Figure out authors and contributors. // Figure out authors and contributors
foreach($xml->xpath('/package/metadata/dc:creator') ?: [] as $author){ foreach($xml->xpath('/package/metadata/dc:creator') ?: [] as $author){
$id = ''; $id = '';
if($author->attributes() !== null){ if($author->attributes() !== null){
$id = $author->attributes()->id; $id = $author->attributes()->id;
} }
$refines = null;
$refinesElement = $xml->xpath('/package/metadata/meta[@property="file-as"][@refines="#' . $id . '"]');
if($refinesElement !== false && sizeof($refinesElement) > 0){
$refines = (string)$refinesElement[0];
}
$this->Authors[] = new Contributor( (string)$author, $this->Authors[] = new Contributor( (string)$author,
(string)$xml->xpath('/package/metadata/meta[@property="file-as"][@refines="#' . $id . '"]')[0], $refines,
$this->NullIfEmpty($xml->xpath('/package/metadata/meta[@property="se:name.person.full-name"][@refines="#' . $id . '"]')), $this->NullIfEmpty($xml->xpath('/package/metadata/meta[@property="se:name.person.full-name"][@refines="#' . $id . '"]')),
$this->NullIfEmpty($xml->xpath('/package/metadata/meta[@property="se:url.encyclopedia.wikipedia"][@refines="#' . $id . '"]')) $this->NullIfEmpty($xml->xpath('/package/metadata/meta[@property="se:url.encyclopedia.wikipedia"][@refines="#' . $id . '"]'))
); );
@ -225,8 +237,20 @@ class Ebook{
$this->Description = $this->NullIfEmpty($xml->xpath('/package/metadata/dc:description')); $this->Description = $this->NullIfEmpty($xml->xpath('/package/metadata/dc:description'));
$this->Language = $this->NullIfEmpty($xml->xpath('/package/metadata/dc:language')); $this->Language = $this->NullIfEmpty($xml->xpath('/package/metadata/dc:language'));
$this->LongDescription = $this->NullIfEmpty($xml->xpath('/package/metadata/meta[@property="se:long-description"]')); $this->LongDescription = $this->NullIfEmpty($xml->xpath('/package/metadata/meta[@property="se:long-description"]'));
$this->WordCount = (int)$xml->xpath('/package/metadata/meta[@property="se:word-count"]')[0] ?? 0;
$this->ReadingEase = (float)$xml->xpath('/package/metadata/meta[@property="se:reading-ease.flesch"]')[0] ?? 0; $wordCount = 0;
$wordCountElement = $xml->xpath('/package/metadata/meta[@property="se:word-count"]');
if($wordCountElement !== false && sizeof($wordCountElement) > 0){
$wordCount = (int)$wordCountElement[0];
}
$this->WordCount = $wordCount;
$readingEase = 0;
$readingEaseElement = $xml->xpath('/package/metadata/meta[@property="se:reading-ease.flesch"]');
if($readingEaseElement !== false && sizeof($readingEaseElement) > 0){
$readingEase = (float)$readingEaseElement[0];
}
$this->ReadingEase = $readingEase;
if($this->ReadingEase !== null){ if($this->ReadingEase !== null){
if($this->ReadingEase >= 90){ if($this->ReadingEase >= 90){
@ -479,9 +503,10 @@ class Ebook{
return $object; return $object;
} }
/**
* @param array<Contributor> $contributors
*/
private function GenerateContributorList(array $contributors): string{ private function GenerateContributorList(array $contributors): string{
// Inputs: An array of Contributor objects.
$string = ''; $string = '';
$i = 0; $i = 0;
foreach($contributors as $contributor){ foreach($contributors as $contributor){

View file

@ -1,10 +1,12 @@
<? <?
use Safe\DateTimeImmutable;
class GitCommit{ class GitCommit{
public $Timestamp; public $Timestamp;
public $Message; public $Message;
public function __construct(string $unixTimestamp, string $message){ public function __construct(string $unixTimestamp, string $message){
$this->Timestamp = new \DateTimeImmutable('@' . $unixTimestamp); $this->Timestamp = new DateTimeImmutable('@' . $unixTimestamp);
$this->Message = $message; $this->Message = $message;
} }
} }

View file

@ -1,6 +1,6 @@
<? <?
class HttpInput{ class HttpInput{
public static function GetString(string $variable, bool $allowEmptyString = true, $default = null): ?string{ public static function GetString(string $variable, bool $allowEmptyString = true, string $default = null): ?string{
$var = self::GetHttpVar($variable, HTTP_VAR_STR, GET, $default); $var = self::GetHttpVar($variable, HTTP_VAR_STR, GET, $default);
if(!$allowEmptyString && $var === ''){ if(!$allowEmptyString && $var === ''){
@ -10,15 +10,15 @@ class HttpInput{
return $var; return $var;
} }
public static function GetInt(string $variable, $default = null): ?int{ public static function GetInt(string $variable, int $default = null): ?int{
return self::GetHttpVar($variable, HTTP_VAR_INT, GET, $default); return self::GetHttpVar($variable, HTTP_VAR_INT, GET, $default);
} }
public static function GetBool(string $variable, $default = null): ?bool{ public static function GetBool(string $variable, bool $default = null): ?bool{
return self::GetHttpVar($variable, HTTP_VAR_BOOL, GET, $default); return self::GetHttpVar($variable, HTTP_VAR_BOOL, GET, $default);
} }
public static function GetDec(string $variable, $default = null): ?float{ public static function GetDec(string $variable, float $default = null): ?float{
return self::GetHttpVar($variable, HTTP_VAR_DEC, GET, $default); return self::GetHttpVar($variable, HTTP_VAR_DEC, GET, $default);
} }
@ -43,7 +43,6 @@ class HttpInput{
switch($type){ switch($type){
case HTTP_VAR_STR: case HTTP_VAR_STR:
return $var; return $var;
break;
case HTTP_VAR_INT: case HTTP_VAR_INT:
// 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($var, '.') === false){ if(is_numeric($var) && mb_strpos($var, '.') === false){
@ -62,7 +61,6 @@ class HttpInput{
else{ else{
return true; return true;
} }
break;
case HTTP_VAR_DEC: case HTTP_VAR_DEC:
if(is_numeric($var)){ if(is_numeric($var)){
try{ try{

View file

@ -6,6 +6,9 @@ use function Safe\unlink;
use function Safe\usort; use function Safe\usort;
class Library{ class Library{
/**
* @return array<Ebook>
*/
public static function GetEbooks(string $sort = null): array{ public static function GetEbooks(string $sort = null): array{
$ebooks = []; $ebooks = [];
@ -69,6 +72,9 @@ class Library{
return $ebooks; return $ebooks;
} }
/**
* @return array<Ebook>
*/
public static function GetEbooksByAuthor(string $wwwFilesystemPath): array{ public static function GetEbooksByAuthor(string $wwwFilesystemPath): array{
// Do we have the author's ebooks cached? // Do we have the author's ebooks cached?
$ebooks = []; $ebooks = [];
@ -82,6 +88,9 @@ class Library{
return $ebooks; return $ebooks;
} }
/**
* @return array<Ebook>
*/
public static function GetEbooksByTag(string $tag): array{ public static function GetEbooksByTag(string $tag): array{
// Do we have the tag's ebooks cached? // Do we have the tag's ebooks cached?
$ebooks = []; $ebooks = [];
@ -95,6 +104,9 @@ class Library{
return $ebooks; return $ebooks;
} }
/**
* @return array<Ebook>
*/
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?
$ebooks = []; $ebooks = [];
@ -108,6 +120,9 @@ class Library{
return $ebooks; return $ebooks;
} }
/**
* @return array<Ebook>
*/
public static function Search(string $query): array{ public static function Search(string $query): array{
$ebooks = Library::GetEbooks(); $ebooks = Library::GetEbooks();
$matches = []; $matches = [];

View file

@ -5,7 +5,7 @@ use function Safe\fclose;
use function Safe\error_log; use function Safe\error_log;
class Logger{ class Logger{
public static function WriteGithubWebhookLogEntry(string $requestId, string $text){ public static function WriteGithubWebhookLogEntry(string $requestId, string $text): void{
try{ try{
$fp = fopen(GITHUB_WEBHOOK_LOG_FILE_PATH, 'a+'); $fp = fopen(GITHUB_WEBHOOK_LOG_FILE_PATH, 'a+');
} }
@ -18,7 +18,7 @@ class Logger{
fclose($fp); fclose($fp);
} }
public static function WriteErrorLogEntry(string $text){ public static function WriteErrorLogEntry(string $text): void{
error_log($text); error_log($text);
} }
} }

View file

@ -2,7 +2,7 @@
class SeeOtherEbookException extends \Exception{ class SeeOtherEbookException extends \Exception{
public $Url; public $Url;
public function __construct($url = ''){ public function __construct(string $url = ''){
$this->Url = $url; $this->Url = $url;
parent::__construct('This ebook is at a different URL: ' . $url); parent::__construct('This ebook is at a different URL: ' . $url);
} }

View file

@ -2,7 +2,7 @@
class WebhookException extends \Exception{ class WebhookException extends \Exception{
public $PostData; public $PostData;
public function __construct($message = '', $data = null){ public function __construct(string $message = '', string $data = null){
$this->PostData = $data; $this->PostData = $data;
parent::__construct($message); parent::__construct($message);
} }

View file

@ -41,7 +41,6 @@ try{
// Silence on success. // Silence on success.
Logger::WriteGithubWebhookLogEntry($requestId, 'Event type: ping.'); Logger::WriteGithubWebhookLogEntry($requestId, 'Event type: ping.');
throw new NoopException(); throw new NoopException();
break;
case 'push': case 'push':
Logger::WriteGithubWebhookLogEntry($requestId, 'Event type: push.'); Logger::WriteGithubWebhookLogEntry($requestId, 'Event type: push.');
@ -114,7 +113,6 @@ try{
break; break;
default: default:
throw new WebhookException('Unrecognized GitHub webhook event.', $post); throw new WebhookException('Unrecognized GitHub webhook event.', $post);
break;
} }
// "Success, no content" // "Success, no content"