diff options
46 files changed, 183 insertions, 169 deletions
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 2fcc5eda6..0e98d1e16 100644 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -47,10 +47,11 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController { $url = trim($url); /** @var string|null $url */ - $url = Minz_ExtensionManager::callHook('check_url_before_add', $url); - if (null === $url) { + $urlHooked = Minz_ExtensionManager::callHook('check_url_before_add', $url); + if ($urlHooked === $url) { throw new FreshRSS_FeedNotAdded_Exception($url); } + $url = $urlHooked; $cat = null; if ($cat_id > 0) { diff --git a/app/Controllers/tagController.php b/app/Controllers/tagController.php index b8db23f3e..69844f7bc 100644 --- a/app/Controllers/tagController.php +++ b/app/Controllers/tagController.php @@ -126,7 +126,8 @@ class FreshRSS_tag_Controller extends FreshRSS_ActionController { $sourceId = Minz_Request::param('id_tag'); if ($targetName == '' || $sourceId == '') { - return Minz_Error::error(400); + Minz_Error::error(400); + return; } $tagDAO = FreshRSS_Factory::createTagDao(); diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php index 89489e590..f49406b13 100644 --- a/app/Controllers/userController.php +++ b/app/Controllers/userController.php @@ -431,11 +431,13 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController { } elseif (FreshRSS_Auth::hasAccess()) { $user_config = FreshRSS_Context::$user_conf; } else { - return Minz_Error::error(403); + Minz_Error::error(403); + return; } if (!FreshRSS_UserDAO::exists($username) || $user_config === null) { - return Minz_Error::error(404); + Minz_Error::error(404); + return; } if ($user_config->email_validation_token === '') { diff --git a/app/Exceptions/AlreadySubscribedException.php b/app/Exceptions/AlreadySubscribedException.php index 33b9f9555..c2b11d3a0 100644 --- a/app/Exceptions/AlreadySubscribedException.php +++ b/app/Exceptions/AlreadySubscribedException.php @@ -1,14 +1,16 @@ <?php class FreshRSS_AlreadySubscribed_Exception extends Exception { + + /** @var string */ private $feedName = ''; - public function __construct($url, $feedName) { + public function __construct(string $url, string $feedName) { parent::__construct('Already subscribed! ' . $url, 2135); $this->feedName = $feedName; } - public function feedName() { + public function feedName(): string { return $this->feedName; } } diff --git a/app/Exceptions/BadUrlException.php b/app/Exceptions/BadUrlException.php index d2509e4ba..748a619d6 100644 --- a/app/Exceptions/BadUrlException.php +++ b/app/Exceptions/BadUrlException.php @@ -2,7 +2,7 @@ class FreshRSS_BadUrl_Exception extends FreshRSS_Feed_Exception { - public function __construct($url) { + public function __construct(string $url) { parent::__construct('`' . $url . '` is not a valid URL'); } diff --git a/app/Exceptions/FeedNotAddedException.php b/app/Exceptions/FeedNotAddedException.php index 59fa74b16..b10e93f05 100644 --- a/app/Exceptions/FeedNotAddedException.php +++ b/app/Exceptions/FeedNotAddedException.php @@ -1,14 +1,16 @@ <?php class FreshRSS_FeedNotAdded_Exception extends Exception { + + /** @var string */ private $url = ''; - public function __construct($url) { + public function __construct(string $url) { parent::__construct('Feed not added! ' . $url, 2147); $this->url = $url; } - public function url() { + public function url(): string { return $this->url; } } diff --git a/app/Exceptions/ZipException.php b/app/Exceptions/ZipException.php index 9ed40c4cb..ecf546533 100644 --- a/app/Exceptions/ZipException.php +++ b/app/Exceptions/ZipException.php @@ -1,14 +1,16 @@ <?php class FreshRSS_Zip_Exception extends Exception { + + /** @var int */ private $zipErrorCode = 0; - public function __construct($zipErrorCode) { + public function __construct(int $zipErrorCode) { parent::__construct('ZIP error!', 2141); $this->zipErrorCode = $zipErrorCode; } - public function zipErrorCode() { + public function zipErrorCode(): int { return $this->zipErrorCode; } } diff --git a/app/Mailers/UserMailer.php b/app/Mailers/UserMailer.php index 4450bd96c..c722a5520 100644 --- a/app/Mailers/UserMailer.php +++ b/app/Mailers/UserMailer.php @@ -10,7 +10,7 @@ class FreshRSS_User_Mailer extends Minz_Mailer { */ protected $view; - public function send_email_need_validation($username, $user_config) { + public function send_email_need_validation(string $username, FreshRSS_UserConfiguration $user_config): bool { Minz_Translate::reset($user_config->language); $this->view->_path('user_mailer/email_need_validation.txt.php'); diff --git a/app/Models/BooleanSearch.php b/app/Models/BooleanSearch.php index 279040a5a..f2e16f972 100644 --- a/app/Models/BooleanSearch.php +++ b/app/Models/BooleanSearch.php @@ -10,10 +10,11 @@ class FreshRSS_BooleanSearch { /** @var array<FreshRSS_BooleanSearch|FreshRSS_Search> */ private $searches = array(); - /** @var string 'AND' or 'OR' or 'AND NOT' */ + /** @var 'AND'|'OR'|'AND NOT' */ private $operator; - public function __construct(string $input, int $level = 0, $operator = 'AND') { + /** @param 'AND'|'OR'|'AND NOT' $operator */ + public function __construct(string $input, int $level = 0, string $operator = 'AND') { $this->operator = $operator; $input = trim($input); if ($input == '') { @@ -221,7 +222,7 @@ class FreshRSS_BooleanSearch { return false; } - private function parseOrSegments(string $input) { + private function parseOrSegments(string $input): void { $input = trim($input); if ($input == '') { return; @@ -258,13 +259,13 @@ class FreshRSS_BooleanSearch { return $this->searches; } - /** @return string 'AND' or 'OR' depending on how this BooleanSearch should be combined */ + /** @return 'AND'|'OR'|'AND NOT' depending on how this BooleanSearch should be combined */ public function operator(): string { return $this->operator; } /** @param FreshRSS_BooleanSearch|FreshRSS_Search $search */ - public function add($search) { + public function add($search): void { $this->searches[] = $search; } diff --git a/app/Models/CategoryDAO.php b/app/Models/CategoryDAO.php index 02845ebe7..dd97bd6cc 100644 --- a/app/Models/CategoryDAO.php +++ b/app/Models/CategoryDAO.php @@ -75,7 +75,8 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo { return false; } - protected function autoUpdateDb(array $errorInfo) { + /** @param array<string> $errorInfo */ + protected function autoUpdateDb(array $errorInfo): bool { if (isset($errorInfo[0])) { if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_FIELD_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_COLUMN) { $errorLines = explode("\n", $errorInfo[2], 2); // The relevant column name is on the first line, other lines are noise diff --git a/app/Models/CategoryDAOSQLite.php b/app/Models/CategoryDAOSQLite.php index 363ffb427..870106f20 100644 --- a/app/Models/CategoryDAOSQLite.php +++ b/app/Models/CategoryDAOSQLite.php @@ -2,7 +2,8 @@ class FreshRSS_CategoryDAOSQLite extends FreshRSS_CategoryDAO { - protected function autoUpdateDb(array $errorInfo) { + /** @param array<string> $errorInfo */ + protected function autoUpdateDb(array $errorInfo): bool { if ($tableInfo = $this->pdo->query("PRAGMA table_info('category')")) { $columns = $tableInfo->fetchAll(PDO::FETCH_COLUMN, 1); foreach (['kind', 'lastUpdate', 'error', 'attributes'] as $column) { diff --git a/app/Models/DatabaseDAO.php b/app/Models/DatabaseDAO.php index bf9cbb2d3..28dd36cd9 100644 --- a/app/Models/DatabaseDAO.php +++ b/app/Models/DatabaseDAO.php @@ -63,13 +63,15 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { return count(array_keys($tables, true, true)) == count($tables); } + /** @return array<array<string,string|bool>> */ public function getSchema(string $table): array { $sql = 'DESC `_' . $table . '`'; $stm = $this->pdo->query($sql); return $this->listDaoToSchema($stm->fetchAll(PDO::FETCH_ASSOC)); } - public function checkTable(string $table, $schema): bool { + /** @param array<string> $schema */ + public function checkTable(string $table, array $schema): bool { $columns = $this->getSchema($table); $ok = (count($columns) == count($schema)); @@ -120,6 +122,10 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { )); } + /** + * @param array<string,string> $dao + * @return array<string,string|bool> + */ public function daoToSchema(array $dao): array { return array( 'name' => $dao['Field'], @@ -129,7 +135,11 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { ); } - public function listDaoToSchema($listDAO): array { + /** + * @param array<array<string,string>> $listDAO + * @return array<array<string,string|bool>> + */ + public function listDaoToSchema(array $listDAO): array { $list = array(); foreach ($listDAO as $dao) { @@ -185,14 +195,14 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { return $ok; } - public function minorDbMaintenance() { + public function minorDbMaintenance(): void { $catDAO = FreshRSS_Factory::createCategoryDao(); $catDAO->resetDefaultCategoryName(); $this->ensureCaseInsensitiveGuids(); } - private static function stdError($error): bool { + private static function stdError(string $error): bool { if (defined('STDERR')) { fwrite(STDERR, $error . "\n"); } diff --git a/app/Models/DatabaseDAOPGSQL.php b/app/Models/DatabaseDAOPGSQL.php index 6ff706250..b1db0f347 100644 --- a/app/Models/DatabaseDAOPGSQL.php +++ b/app/Models/DatabaseDAOPGSQL.php @@ -33,6 +33,7 @@ class FreshRSS_DatabaseDAOPGSQL extends FreshRSS_DatabaseDAOSQLite { return count(array_keys($tables, true, true)) == count($tables); } + /** @return array<array<string,string|bool>> */ public function getSchema(string $table): array { $sql = 'select column_name as field, data_type as type, column_default as default, is_nullable as null from INFORMATION_SCHEMA.COLUMNS where table_name = ?'; $stm = $this->pdo->prepare($sql); @@ -40,6 +41,10 @@ class FreshRSS_DatabaseDAOPGSQL extends FreshRSS_DatabaseDAOSQLite { return $this->listDaoToSchema($stm->fetchAll(PDO::FETCH_ASSOC)); } + /** + * @param array<string,string> $dao + * @return array<string,string|bool> + */ public function daoToSchema(array $dao): array { return array( 'name' => $dao['field'], diff --git a/app/Models/DatabaseDAOSQLite.php b/app/Models/DatabaseDAOSQLite.php index e5a6f5a04..3fab1134d 100644 --- a/app/Models/DatabaseDAOSQLite.php +++ b/app/Models/DatabaseDAOSQLite.php @@ -25,6 +25,7 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO { return count(array_keys($tables, true, true)) == count($tables); } + /** @return array<array<string,string|bool>> */ public function getSchema(string $table): array { $sql = 'PRAGMA table_info(' . $table . ')'; $stm = $this->pdo->query($sql); @@ -45,6 +46,10 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO { )); } + /** + * @param array<string,string> $dao + * @return array<string,string|bool> + */ public function daoToSchema(array $dao): array { return [ 'name' => $dao['name'], diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php index 1047a218b..2a123e0db 100644 --- a/app/Models/FeedDAO.php +++ b/app/Models/FeedDAO.php @@ -19,7 +19,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo { return false; } - protected function autoUpdateDb(array $errorInfo) { + /** @param array<string> $errorInfo */ + protected function autoUpdateDb(array $errorInfo): bool { if (isset($errorInfo[0])) { if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_FIELD_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_COLUMN) { $errorLines = explode("\n", $errorInfo[2], 2); // The relevant column name is on the first line, other lines are noise diff --git a/app/Models/FeedDAOSQLite.php b/app/Models/FeedDAOSQLite.php index a4432ea62..08a352d5f 100644 --- a/app/Models/FeedDAOSQLite.php +++ b/app/Models/FeedDAOSQLite.php @@ -2,7 +2,8 @@ class FreshRSS_FeedDAOSQLite extends FreshRSS_FeedDAO { - protected function autoUpdateDb(array $errorInfo) { + /** @param array<string> $errorInfo */ + protected function autoUpdateDb(array $errorInfo): bool { if ($tableInfo = $this->pdo->query("PRAGMA table_info('feed')")) { $columns = $tableInfo->fetchAll(PDO::FETCH_COLUMN, 1); foreach (['attributes', 'kind'] as $column) { diff --git a/app/Models/ReadingMode.php b/app/Models/ReadingMode.php index ddb413315..6f2fc889c 100644 --- a/app/Models/ReadingMode.php +++ b/app/Models/ReadingMode.php @@ -28,12 +28,9 @@ class FreshRSS_ReadingMode { /** * ReadingMode constructor. - * @param string $id - * @param string $title - * @param string[] $urlParams - * @param bool $active + * @param array<string> $urlParams */ - public function __construct($id, $title, $urlParams, $active) { + public function __construct(string $id, string $title, array $urlParams, bool $active) { $this->id = $id; $this->name = _i($id); $this->title = $title; @@ -41,41 +38,24 @@ class FreshRSS_ReadingMode { $this->isActive = $active; } - /** - * @return string - */ - public function getId() { + public function getId(): string { return $this->id; } - /** - * @return string - */ - public function getName() { + public function getName(): string { return $this->name; } - /** - * @param string $name - * @return FreshRSS_ReadingMode - */ - public function setName($name) { + public function setName(string $name): FreshRSS_ReadingMode { $this->name = $name; return $this; } - /** - * @return string - */ - public function getTitle() { + public function getTitle(): string { return $this->title; } - /** - * @param string $title - * @return FreshRSS_ReadingMode - */ - public function setTitle($title) { + public function setTitle(string $title): FreshRSS_ReadingMode { $this->title = $title; return $this; } @@ -83,40 +63,31 @@ class FreshRSS_ReadingMode { /** * @return array<string> */ - public function getUrlParams() { + public function getUrlParams(): array { return $this->urlParams; } /** * @param array<string> $urlParams - * @return FreshRSS_ReadingMode */ - public function setUrlParams($urlParams) { + public function setUrlParams(array $urlParams): FreshRSS_ReadingMode { $this->urlParams = $urlParams; return $this; } - /** - * @return bool - */ - public function isActive() { + public function isActive(): bool { return $this->isActive; } - /** - * @param bool $isActive - * @return FreshRSS_ReadingMode - */ - public function setIsActive($isActive) { + public function setIsActive(bool $isActive): FreshRSS_ReadingMode { $this->isActive = $isActive; return $this; } /** - * Returns the built-in reading modes. - * return ReadingMode[] + * @return array<FreshRSS_ReadingMode> the built-in reading modes */ - public static function getReadingModes() { + public static function getReadingModes(): array { $actualView = Minz_Request::actionName(); $defaultCtrl = Minz_Request::defaultControllerName(); $isDefaultCtrl = Minz_Request::controllerName() === $defaultCtrl; diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php index ca927ef38..8dc392160 100644 --- a/app/Models/TagDAO.php +++ b/app/Models/TagDAO.php @@ -30,7 +30,8 @@ class FreshRSS_TagDAO extends Minz_ModelPdo { return $ok; } - protected function autoUpdateDb(array $errorInfo) { + /** @param array<string> $errorInfo */ + protected function autoUpdateDb(array $errorInfo): bool { if (isset($errorInfo[0])) { if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_TABLE_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_TABLE) { if (stripos($errorInfo[2], 'tag') !== false) { diff --git a/app/Models/TagDAOSQLite.php b/app/Models/TagDAOSQLite.php index 530669699..910455546 100644 --- a/app/Models/TagDAOSQLite.php +++ b/app/Models/TagDAOSQLite.php @@ -6,7 +6,8 @@ class FreshRSS_TagDAOSQLite extends FreshRSS_TagDAO { return 'OR IGNORE'; } - protected function autoUpdateDb(array $errorInfo) { + /** @param array<string> $errorInfo */ + protected function autoUpdateDb(array $errorInfo): bool { if ($tableInfo = $this->pdo->query("SELECT sql FROM sqlite_master where name='tag'")) { $showCreate = $tableInfo->fetchColumn(); if (stripos($showCreate, 'tag') === false) { diff --git a/app/Models/UserDAO.php b/app/Models/UserDAO.php index 9f91df80e..8ba50cc29 100644 --- a/app/Models/UserDAO.php +++ b/app/Models/UserDAO.php @@ -1,7 +1,8 @@ <?php class FreshRSS_UserDAO extends Minz_ModelPdo { - public function createUser() { + + public function createUser(): bool { require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); try { @@ -21,7 +22,7 @@ class FreshRSS_UserDAO extends Minz_ModelPdo { } } - public function deleteUser() { + public function deleteUser(): bool { if (defined('STDERR')) { fwrite(STDERR, 'Deleting SQL data for user “' . $this->current_user . "”…\n"); } @@ -38,18 +39,18 @@ class FreshRSS_UserDAO extends Minz_ModelPdo { } } - public static function exists($username) { + public static function exists(string $username): bool { return is_dir(USERS_PATH . '/' . $username); } - public static function touch($username = '') { + public static function touch(string $username = ''): bool { if (!FreshRSS_user_Controller::checkUsername($username)) { $username = Minz_User::name() ?? Minz_User::INTERNAL_USER; } return touch(USERS_PATH . '/' . $username . '/config.php'); } - public static function mtime($username) { - return @filemtime(USERS_PATH . '/' . $username . '/config.php'); + public static function mtime(string $username): int { + return @(int)filemtime(USERS_PATH . '/' . $username . '/config.php'); } } diff --git a/cli/i18n/I18nCompletionValidator.php b/cli/i18n/I18nCompletionValidator.php index 000629f8d..3903e18cd 100644 --- a/cli/i18n/I18nCompletionValidator.php +++ b/cli/i18n/I18nCompletionValidator.php @@ -4,18 +4,27 @@ require_once __DIR__ . '/I18nValidatorInterface.php'; class I18nCompletionValidator implements I18nValidatorInterface { + /** @var array<string,array<string,I18nValue>> */ private $reference; + /** @var array<string,array<string,I18nValue>> */ private $language; + /** @var int */ private $totalEntries = 0; + /** @var int */ private $passEntries = 0; + /** @var string */ private $result = ''; - public function __construct($reference, $language) { + /** + * @param array<string,array<string,I18nValue>> $reference + * @param array<string,array<string,I18nValue>> $language + */ + public function __construct(array $reference, array $language) { $this->reference = $reference; $this->language = $language; } - public function displayReport() { + public function displayReport(): string { if ($this->passEntries > $this->totalEntries) { throw new \RuntimeException('The number of translated strings cannot be higher than the number of strings'); } @@ -25,11 +34,11 @@ class I18nCompletionValidator implements I18nValidatorInterface { return sprintf('Translation is %5.1f%% complete.', $this->passEntries / $this->totalEntries * 100) . PHP_EOL; } - public function displayResult() { + public function displayResult(): string { return $this->result; } - public function validate() { + public function validate(): bool { foreach ($this->reference as $file => $data) { foreach ($data as $refKey => $refValue) { $this->totalEntries++; diff --git a/cli/i18n/I18nUsageValidator.php b/cli/i18n/I18nUsageValidator.php index 681e17326..f507fbac3 100644 --- a/cli/i18n/I18nUsageValidator.php +++ b/cli/i18n/I18nUsageValidator.php @@ -4,18 +4,27 @@ require_once __DIR__ . '/I18nValidatorInterface.php'; class I18nUsageValidator implements I18nValidatorInterface { + /** @var array<string> */ private $code; + /** @var array<string,array<string,string>> */ private $reference; + /** @var int */ private $totalEntries = 0; + /** @var int */ private $failedEntries = 0; + /** @var string */ private $result = ''; - public function __construct($reference, $code) { + /** + * @param array<string,array<string,string>> $reference + * @param array<string> $code + */ + public function __construct(array $reference, array $code) { $this->code = $code; $this->reference = $reference; } - public function displayReport() { + public function displayReport(): string { if ($this->failedEntries > $this->totalEntries) { throw new \RuntimeException('The number of unused strings cannot be higher than the number of strings'); } @@ -25,11 +34,11 @@ class I18nUsageValidator implements I18nValidatorInterface { return sprintf('%5.1f%% of translation keys are unused.', $this->failedEntries / $this->totalEntries * 100) . PHP_EOL; } - public function displayResult() { + public function displayResult(): string { return $this->result; } - public function validate() { + public function validate(): bool { foreach ($this->reference as $file => $data) { foreach ($data as $key => $value) { $this->totalEntries++; diff --git a/cli/i18n/I18nValidatorInterface.php b/cli/i18n/I18nValidatorInterface.php index d5681912b..e6f5f7cdd 100644 --- a/cli/i18n/I18nValidatorInterface.php +++ b/cli/i18n/I18nValidatorInterface.php @@ -5,21 +5,14 @@ interface I18nValidatorInterface { /** * Display the validation result. * Empty if there are no errors. - * - * @return array */ - public function displayResult(); + public function displayResult(): string; - /** - * @return bool - */ - public function validate(); + public function validate(): bool; /** * Display the validation report. - * - * @return string */ - public function displayReport(); + public function displayReport(): string; } diff --git a/lib/Minz/ActionException.php b/lib/Minz/ActionException.php index 53f0aab04..3c08b4892 100644 --- a/lib/Minz/ActionException.php +++ b/lib/Minz/ActionException.php @@ -1,6 +1,6 @@ <?php class Minz_ActionException extends Minz_Exception { - public function __construct ($controller_name, $action_name, $code = self::ERROR) { + public function __construct(string $controller_name, string $action_name, int $code = self::ERROR) { // Just for security, as we are not supposed to get non-alphanumeric characters. $action_name = rawurlencode($action_name); diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index 6d4aed0ab..a9a4ae03a 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -8,7 +8,7 @@ * @property-read string $environment * @property-read array<string> $extensions_enabled * @property-read string $mailer - * @property-read string $smtp + * @property-read array<string|int|bool> $smtp * @property string $title */ class Minz_Configuration { diff --git a/lib/Minz/ConfigurationException.php b/lib/Minz/ConfigurationException.php index f294c3341..498420a67 100644 --- a/lib/Minz/ConfigurationException.php +++ b/lib/Minz/ConfigurationException.php @@ -1,7 +1,7 @@ <?php class Minz_ConfigurationException extends Minz_Exception { - public function __construct($error, $code = self::ERROR) { + public function __construct(string $error, int $code = self::ERROR) { $message = 'Configuration error: ' . $error; parent::__construct($message, $code); } diff --git a/lib/Minz/ControllerNotActionControllerException.php b/lib/Minz/ControllerNotActionControllerException.php index 5cf418404..19e5df1b4 100644 --- a/lib/Minz/ControllerNotActionControllerException.php +++ b/lib/Minz/ControllerNotActionControllerException.php @@ -1,6 +1,6 @@ <?php class Minz_ControllerNotActionControllerException extends Minz_Exception { - public function __construct ($controller_name, $code = self::ERROR) { + public function __construct(string $controller_name, int $code = self::ERROR) { $message = 'Controller `' . $controller_name . '` isn’t instance of ActionController'; parent::__construct ($message, $code); diff --git a/lib/Minz/ControllerNotExistException.php b/lib/Minz/ControllerNotExistException.php index a024e1cbd..2d2178974 100644 --- a/lib/Minz/ControllerNotExistException.php +++ b/lib/Minz/ControllerNotExistException.php @@ -1,6 +1,6 @@ <?php class Minz_ControllerNotExistException extends Minz_Exception { - public function __construct ($code = self::ERROR) { + public function __construct(int $code = self::ERROR) { $message = 'Controller not found!'; parent::__construct ($message, $code); } diff --git a/lib/Minz/CurrentPagePaginationException.php b/lib/Minz/CurrentPagePaginationException.php index 3e3d9d1b4..973913afb 100644 --- a/lib/Minz/CurrentPagePaginationException.php +++ b/lib/Minz/CurrentPagePaginationException.php @@ -1,6 +1,6 @@ <?php class Minz_CurrentPagePaginationException extends Minz_Exception { - public function __construct ($page) { + public function __construct(int $page) { $message = 'Page number `' . $page . '` doesn\'t exist'; parent::__construct ($message, self::ERROR); diff --git a/lib/Minz/Error.php b/lib/Minz/Error.php index 3162c6f99..e23499a10 100644 --- a/lib/Minz/Error.php +++ b/lib/Minz/Error.php @@ -19,7 +19,7 @@ class Minz_Error { * > $logs['notice'] * @param bool $redirect indique s'il faut forcer la redirection (les logs ne seront pas transmis) */ - public static function error ($code = 404, $logs = array (), $redirect = true) { + public static function error(int $code = 404, array $logs = [], bool $redirect = true): void { $logs = self::processLogs ($logs); $error_filename = APP_PATH . '/Controllers/errorController.php'; @@ -52,7 +52,7 @@ class Minz_Error { * @param array<string,string>|string $logs logs sorted by category (error, warning, notice) * @return array<string> list of matching logs, without the category, according to environment preferences (production / development) */ - private static function processLogs ($logs) { + private static function processLogs($logs) { $conf = Minz_Configuration::get('system'); $env = $conf->environment; $logs_ok = array (); diff --git a/lib/Minz/Exception.php b/lib/Minz/Exception.php index b5e71e0d8..f2d3b876b 100644 --- a/lib/Minz/Exception.php +++ b/lib/Minz/Exception.php @@ -4,7 +4,7 @@ class Minz_Exception extends Exception { const WARNING = 10; const NOTICE = 20; - public function __construct ($message, $code = self::ERROR) { + public function __construct(string $message, int $code = self::ERROR) { if ($code != Minz_Exception::ERROR && $code != Minz_Exception::WARNING && $code != Minz_Exception::NOTICE) { diff --git a/lib/Minz/ExtensionException.php b/lib/Minz/ExtensionException.php index b86a97798..c5bba60a9 100644 --- a/lib/Minz/ExtensionException.php +++ b/lib/Minz/ExtensionException.php @@ -1,7 +1,7 @@ <?php class Minz_ExtensionException extends Minz_Exception { - public function __construct ($message, $extension_name = false, $code = self::ERROR) { + public function __construct(string $message, ?string $extension_name = null, int $code = self::ERROR) { if ($extension_name) { $message = 'An error occurred in `' . $extension_name . '` extension with the message: ' . $message; } else { diff --git a/lib/Minz/FileNotExistException.php b/lib/Minz/FileNotExistException.php index f97f161af..b467a5208 100644 --- a/lib/Minz/FileNotExistException.php +++ b/lib/Minz/FileNotExistException.php @@ -1,6 +1,6 @@ <?php class Minz_FileNotExistException extends Minz_Exception { - public function __construct ($file_name, $code = self::ERROR) { + public function __construct(string $file_name, int $code = self::ERROR) { $message = 'File not found: `' . $file_name.'`'; parent::__construct ($message, $code); diff --git a/lib/Minz/Helper.php b/lib/Minz/Helper.php index 2c011e1bf..3e09c4758 100644 --- a/lib/Minz/Helper.php +++ b/lib/Minz/Helper.php @@ -12,6 +12,8 @@ class Minz_Helper { /** * Wrapper for htmlspecialchars. * Force UTf-8 value and can be used on array too. + * @param string|array<string> $var + * @return string|array<string> */ public static function htmlspecialchars_utf8($var) { if (is_array($var)) { diff --git a/lib/Minz/Mailer.php b/lib/Minz/Mailer.php index 92e396f99..ba434ec8f 100644 --- a/lib/Minz/Mailer.php +++ b/lib/Minz/Mailer.php @@ -32,8 +32,11 @@ class Minz_Mailer { */ protected $view; + /** @var string */ private $mailer; + /** @var array<string|int|bool> */ private $smtp_config; + /** @var int */ private $debug_level; /** diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php index b8c1ad89b..0e813ddca 100644 --- a/lib/Minz/ModelPdo.php +++ b/lib/Minz/ModelPdo.php @@ -12,6 +12,7 @@ class Minz_ModelPdo { /** * Shares the connection to the database between all instances. + * @var bool */ public static $usesSharedPdo = true; diff --git a/lib/Minz/PDOConnectionException.php b/lib/Minz/PDOConnectionException.php index 11e4d1029..2b015607e 100644 --- a/lib/Minz/PDOConnectionException.php +++ b/lib/Minz/PDOConnectionException.php @@ -1,6 +1,6 @@ <?php class Minz_PDOConnectionException extends Minz_Exception { - public function __construct ($error, $user, $code = self::ERROR) { + public function __construct(string $error, string $user, int $code = self::ERROR) { $message = 'Access to database is denied for `' . $user . '`: ' . $error; parent::__construct ($message, $code); diff --git a/lib/Minz/Pdo.php b/lib/Minz/Pdo.php index 8c9cd9076..2efff61d4 100644 --- a/lib/Minz/Pdo.php +++ b/lib/Minz/Pdo.php @@ -6,18 +6,20 @@ */ abstract class Minz_Pdo extends PDO { - public function __construct(string $dsn, $username = null, $passwd = null, $options = null) { + /** @param array<int,int|string>|null $options */ + public function __construct(string $dsn, ?string $username = null, ?string $passwd = null, ?array $options = null) { parent::__construct($dsn, $username, $passwd, $options); $this->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); } - abstract public function dbType(); + abstract public function dbType(): string; + /** @var string */ private $prefix = ''; public function prefix(): string { return $this->prefix; } - public function setPrefix(string $prefix) { + public function setPrefix(string $prefix): void { $this->prefix = $prefix; } @@ -33,6 +35,10 @@ abstract class Minz_Pdo extends PDO { } // PHP8+: PDO::lastInsertId(?string $name = null): string|false + /** + * @param string|null $name + * @return string|false + */ #[\ReturnTypeWillChange] public function lastInsertId($name = null) { if ($name != null) { @@ -42,6 +48,11 @@ abstract class Minz_Pdo extends PDO { } // PHP8+: PDO::prepare(string $query, array $options = []): PDOStatement|false + /** + * @param string $statement + * @param array<int,string>|null $driver_options + * @return PDOStatement|false + */ #[\ReturnTypeWillChange] public function prepare($statement, $driver_options = []) { $statement = $this->preSql($statement); @@ -49,15 +60,19 @@ abstract class Minz_Pdo extends PDO { } // PHP8+: PDO::exec(string $statement): int|false + /** + * @param string $statement + * @return int|false + */ #[\ReturnTypeWillChange] public function exec($statement) { $statement = $this->preSql($statement); return parent::exec($statement); } - // PHP8+: PDO::query(string $query, ?int $fetchMode = null, mixed ...$fetchModeArgs): PDOStatement|false + /** @return PDOStatement|false */ #[\ReturnTypeWillChange] - public function query($query, $fetch_mode = null, ...$fetch_mode_args) { + public function query(string $query, ?int $fetch_mode = null, ...$fetch_mode_args) { $query = $this->preSql($query); return $fetch_mode ? parent::query($query, $fetch_mode, ...$fetch_mode_args) : parent::query($query); } diff --git a/lib/Minz/PdoMysql.php b/lib/Minz/PdoMysql.php index b66cccf28..ee411d949 100644 --- a/lib/Minz/PdoMysql.php +++ b/lib/Minz/PdoMysql.php @@ -6,7 +6,8 @@ */ class Minz_PdoMysql extends Minz_Pdo { - public function __construct(string $dsn, $username = null, $passwd = null, $options = null) { + /** @param array<int,int|string>|null $options */ + public function __construct(string $dsn, ?string $username = null, ?string $passwd = null, ?array $options = null) { parent::__construct($dsn, $username, $passwd, $options); $this->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); } @@ -15,7 +16,10 @@ class Minz_PdoMysql extends Minz_Pdo { return 'mysql'; } - // PHP8+: PDO::lastInsertId(?string $name = null): string|false + /** + * @param string|null $name + * @return string|false + */ #[\ReturnTypeWillChange] public function lastInsertId($name = null) { return parent::lastInsertId(); //We discard the name, only used by PostgreSQL diff --git a/lib/Minz/PdoPgsql.php b/lib/Minz/PdoPgsql.php index cae0fe476..b239d3544 100644 --- a/lib/Minz/PdoPgsql.php +++ b/lib/Minz/PdoPgsql.php @@ -6,7 +6,8 @@ */ class Minz_PdoPgsql extends Minz_Pdo { - public function __construct(string $dsn, $username = null, $passwd = null, $options = null) { + /** @param array<int,int|string>|null $options */ + public function __construct(string $dsn, ?string $username = null, ?string $passwd = null, ?array $options = null) { parent::__construct($dsn, $username, $passwd, $options); $this->exec("SET NAMES 'UTF8';"); } diff --git a/lib/Minz/PdoSqlite.php b/lib/Minz/PdoSqlite.php index 2c90413a1..479879ffe 100644 --- a/lib/Minz/PdoSqlite.php +++ b/lib/Minz/PdoSqlite.php @@ -6,7 +6,8 @@ */ class Minz_PdoSqlite extends Minz_Pdo { - public function __construct(string $dsn, $username = null, $passwd = null, $options = null) { + /** @param array<int,int|string>|null $options */ + public function __construct(string $dsn, ?string $username = null, ?string $passwd = null, ?array $options = null) { parent::__construct($dsn, $username, $passwd, $options); $this->exec('PRAGMA foreign_keys = ON;'); } @@ -15,7 +16,10 @@ class Minz_PdoSqlite extends Minz_Pdo { return 'sqlite'; } - // PHP8+: PDO::lastInsertId(?string $name = null): string|false + /** + * @param string|null $name + * @return string|false + */ #[\ReturnTypeWillChange] public function lastInsertId($name = null) { return parent::lastInsertId(); //We discard the name, only used by PostgreSQL diff --git a/lib/Minz/PermissionDeniedException.php b/lib/Minz/PermissionDeniedException.php index 61be530d3..91a4b310e 100644 --- a/lib/Minz/PermissionDeniedException.php +++ b/lib/Minz/PermissionDeniedException.php @@ -1,6 +1,6 @@ <?php class Minz_PermissionDeniedException extends Minz_Exception { - public function __construct ($file_name, $code = self::ERROR) { + public function __construct(string $file_name, int $code = self::ERROR) { $message = 'Permission is denied for `' . $file_name.'`'; parent::__construct ($message, $code); diff --git a/lib/favicons.php b/lib/favicons.php index fd03f61c8..abaa5e63a 100644 --- a/lib/favicons.php +++ b/lib/favicons.php @@ -2,7 +2,7 @@ const FAVICONS_DIR = DATA_PATH . '/favicons/'; const DEFAULT_FAVICON = PUBLIC_PATH . '/themes/icons/default_favicon.ico'; -function isImgMime($content) { +function isImgMime(string $content): bool { //Based on https://github.com/ArthurHoaro/favicon/blob/3a4f93da9bb24915b21771eb7873a21bde26f5d1/src/Favicon/Favicon.php#L311-L319 if ($content == '') { return false; @@ -21,7 +21,8 @@ function isImgMime($content) { return $isImage; } -function downloadHttp(&$url, $curlOptions = array()) { +/** @param array<int,int|bool> $curlOptions */ +function downloadHttp(string &$url, array $curlOptions = []): string { syslog(LOG_INFO, 'FreshRSS Favicon GET ' . $url); $url = checkUrl($url); if (!$url) { @@ -49,7 +50,7 @@ function downloadHttp(&$url, $curlOptions = array()) { return $info['http_code'] == 200 ? $response : ''; } -function searchFavicon(&$url) { +function searchFavicon(string &$url): string { $dom = new DOMDocument(); $html = downloadHttp($url); if ($html != '' && @$dom->loadHTML($html, LIBXML_NONET | LIBXML_NOERROR | LIBXML_NOWARNING)) { @@ -84,7 +85,7 @@ function searchFavicon(&$url) { return ''; } -function download_favicon($url, $dest) { +function download_favicon(string $url, string $dest): bool { $url = trim($url); $favicon = searchFavicon($url); if ($favicon == '') { diff --git a/lib/lib_date.php b/lib/lib_date.php index cb1f1d1e2..00356927f 100644 --- a/lib/lib_date.php +++ b/lib/lib_date.php @@ -42,13 +42,13 @@ function example($dateInterval) { } */ -function _dateFloor($isoDate) { +function _dateFloor(string $isoDate): string { $x = explode('T', $isoDate, 2); $t = isset($x[1]) ? str_pad($x[1], 6, '0') : '000000'; return str_pad($x[0], 8, '01') . 'T' . $t; } -function _dateCeiling($isoDate) { +function _dateCeiling(string $isoDate): string { $x = explode('T', $isoDate, 2); $t = isset($x[1]) && strlen($x[1]) > 1 ? str_pad($x[1], 6, '59') : '235959'; switch (strlen($x[0])) { @@ -62,11 +62,11 @@ function _dateCeiling($isoDate) { } } -function _noDelimit($isoDate) { +function _noDelimit(?string $isoDate): ?string { return $isoDate === null || $isoDate === '' ? null : str_replace(array('-', ':'), '', $isoDate); //FIXME: Bug with negative time zone } -function _dateRelative($d1, $d2) { +function _dateRelative(?string $d1, ?string $d2): ?string { if ($d2 === null) { return $d1 !== null && $d1[0] !== 'P' ? $d1 : null; } elseif ($d2 !== '' && $d2[0] != 'P' && $d1 !== null && $d1[0] !== 'P') { @@ -81,10 +81,10 @@ function _dateRelative($d1, $d2) { /** * Parameter $dateInterval is a string containing an ISO 8601 time interval. - * Returns an array with the minimum and maximum Unix timestamp of this interval, + * @return array{int|null|false,int|null|false} an array with the minimum and maximum Unix timestamp of this interval, * or null if open interval, or false if error. */ -function parseDateInterval($dateInterval) { +function parseDateInterval(string $dateInterval) { $dateInterval = trim($dateInterval); $dateInterval = str_replace('--', '/', $dateInterval); $dateInterval = strtoupper($dateInterval); diff --git a/lib/lib_install.php b/lib/lib_install.php index 931de21a2..18f4a732a 100644 --- a/lib/lib_install.php +++ b/lib/lib_install.php @@ -3,7 +3,8 @@ Minz_Configuration::register('default_system', join_path(FRESHRSS_PATH, 'config.default.php')); Minz_Configuration::register('default_user', join_path(FRESHRSS_PATH, 'config-user.default.php')); -function checkRequirements($dbType = '') { +/** @return array<string,string> */ +function checkRequirements(string $dbType = ''): array { $php = version_compare(PHP_VERSION, FRESHRSS_MIN_PHP_VERSION) >= 0; $curl = extension_loaded('curl'); $pdo_mysql = extension_loaded('pdo_mysql'); @@ -74,11 +75,11 @@ function checkRequirements($dbType = '') { ); } -function generateSalt() { +function generateSalt(): string { return sha1(uniqid('' . mt_rand(), true).implode('', stat(__FILE__))); } -function initDb() { +function initDb(): string { $conf = FreshRSS_Context::$system_conf; $db = $conf->db; if (empty($db['pdo_options'])) { @@ -115,7 +116,7 @@ function initDb() { return $databaseDAO->testConnection(); } -function setupMigrations() { +function setupMigrations(): bool { $migrations_path = APP_PATH . '/migrations'; $migrations_version_path = DATA_PATH . '/applied_migrations.txt'; diff --git a/tests/phpstan-next.txt b/tests/phpstan-next.txt index 5670b37df..52b3b823c 100644 --- a/tests/phpstan-next.txt +++ b/tests/phpstan-next.txt @@ -8,81 +8,43 @@ ./app/Controllers/feedController.php ./app/Controllers/updateController.php ./app/Controllers/userController.php -./app/Exceptions/AlreadySubscribedException.php -./app/Exceptions/BadUrlException.php -./app/Exceptions/FeedNotAddedException.php -./app/Exceptions/ZipException.php ./app/install.php -./app/Mailers/UserMailer.php ./app/Models/Auth.php -./app/Models/BooleanSearch.php ./app/Models/Category.php ./app/Models/CategoryDAO.php -./app/Models/CategoryDAOSQLite.php ./app/Models/ConfigurationSetter.php -./app/Models/DatabaseDAO.php -./app/Models/DatabaseDAOPGSQL.php -./app/Models/DatabaseDAOSQLite.php ./app/Models/Entry.php ./app/Models/Feed.php ./app/Models/FeedDAO.php -./app/Models/FeedDAOSQLite.php ./app/Models/FilterAction.php ./app/Models/FormAuth.php -./app/Models/ReadingMode.php ./app/Models/Search.php ./app/Models/Share.php ./app/Models/TagDAO.php -./app/Models/TagDAOSQLite.php ./app/Models/Themes.php -./app/Models/UserDAO.php ./app/Models/View.php ./app/Services/ExportService.php ./app/Services/ImportService.php ./cli/_cli.php ./cli/_update-or-create-user.php ./cli/check.translation.php -./cli/i18n/I18nCompletionValidator.php ./cli/i18n/I18nData.php ./cli/i18n/I18nFile.php -./cli/i18n/I18nUsageValidator.php -./cli/i18n/I18nValidatorInterface.php ./cli/i18n/I18nValue.php ./cli/manipulate.translation.php ./lib/core-extensions/Google-Groups/extension.php ./lib/core-extensions/Tumblr-GDPR/extension.php -./lib/favicons.php ./lib/http-conditional.php -./lib/lib_date.php -./lib/lib_install.php ./lib/Minz/ActionController.php -./lib/Minz/ActionException.php ./lib/Minz/Configuration.php -./lib/Minz/ConfigurationException.php -./lib/Minz/ControllerNotActionControllerException.php -./lib/Minz/ControllerNotExistException.php -./lib/Minz/CurrentPagePaginationException.php ./lib/Minz/Dispatcher.php -./lib/Minz/Error.php -./lib/Minz/Exception.php ./lib/Minz/Extension.php -./lib/Minz/ExtensionException.php ./lib/Minz/ExtensionManager.php -./lib/Minz/FileNotExistException.php ./lib/Minz/FrontController.php -./lib/Minz/Helper.php ./lib/Minz/Log.php -./lib/Minz/Mailer.php ./lib/Minz/Migrator.php ./lib/Minz/ModelArray.php -./lib/Minz/ModelPdo.php ./lib/Minz/Paginator.php -./lib/Minz/Pdo.php -./lib/Minz/PDOConnectionException.php -./lib/Minz/PdoMysql.php -./lib/Minz/PdoPgsql.php -./lib/Minz/PdoSqlite.php -./lib/Minz/PermissionDeniedException.php ./lib/Minz/Request.php ./lib/Minz/Session.php ./lib/Minz/Translate.php |
