From f3760f138dcbaf7a2190336a0378cf1b2190c9f5 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 17 Apr 2023 08:30:21 +0200 Subject: Complete PHPStan Level 6 (#5305) * Complete PHPStan Level 6 Fix https://github.com/FreshRSS/FreshRSS/issues/4112 And initiate PHPStan Level 7 * PHPStan Level 6 for tests * Use phpstan/phpstan-phpunit * Update to PHPStan version 1.10 * Fix mixed bug * Fix mixed return bug * Fix paginator bug * Fix FreshRSS_UserConfiguration * A couple more Minz_Configuration bug fixes * A few trivial PHPStan Level 7 fixes * A few more simple PHPStan Level 7 * More files passing PHPStan Level 7 Add interface to replace removed class from https://github.com/FreshRSS/FreshRSS/pull/5251 * A few more PHPStan Level 7 preparations * A few last details --- app/Controllers/categoryController.php | 4 +- app/Controllers/configureController.php | 4 +- app/Controllers/entryController.php | 4 +- app/Controllers/extensionController.php | 6 +- app/Controllers/feedController.php | 9 +- app/Controllers/importExportController.php | 10 +- app/Controllers/indexController.php | 12 +- app/Controllers/javascriptController.php | 6 +- app/Controllers/statsController.php | 4 +- app/Controllers/subscriptionController.php | 12 +- app/Controllers/tagController.php | 15 +- app/Models/Auth.php | 6 +- app/Models/BooleanSearch.php | 2 +- app/Models/Category.php | 2 +- app/Models/CategoryDAO.php | 2 +- app/Models/Context.php | 9 +- app/Models/DatabaseDAO.php | 2 +- app/Models/DatabaseDAOSQLite.php | 9 +- app/Models/Entry.php | 11 +- app/Models/EntryDAO.php | 40 ++-- app/Models/EntryDAOSQLite.php | 36 ++-- app/Models/Factory.php | 12 +- app/Models/Feed.php | 109 ++++++----- app/Models/FeedDAO.php | 8 +- app/Models/Search.php | 6 +- app/Models/Share.php | 4 +- app/Models/StatsDAO.php | 10 +- app/Models/StatsDAOPGSQL.php | 5 +- app/Models/StatsDAOSQLite.php | 3 + app/Models/Tag.php | 2 +- app/Models/TagDAO.php | 4 +- app/Models/TagDAOSQLite.php | 2 +- app/Models/UserQuery.php | 2 +- app/Models/View.php | 4 +- app/Services/ExportService.php | 4 +- app/Services/ImportService.php | 39 ++-- app/Utils/feverUtil.php | 2 +- app/actualize_script.php | 6 +- app/install.php | 88 +++++---- app/views/helpers/export/articles.phtml | 2 +- app/views/helpers/export/opml.phtml | 6 +- app/views/helpers/javascript_vars.phtml | 2 +- app/views/index/logs.phtml | 4 +- app/views/index/normal.phtml | 2 +- app/views/stats/idle.phtml | 2 +- cli/_cli.php | 4 +- cli/_update-or-create-user.php | 2 +- cli/actualize-user.php | 4 +- cli/db-optimize.php | 4 +- cli/delete-user.php | 4 +- cli/export-opml-for-user.php | 4 +- cli/export-sqlite-for-user.php | 4 +- cli/export-zip-for-user.php | 4 +- cli/i18n/I18nData.php | 4 +- cli/import-for-user.php | 4 +- cli/import-sqlite-for-user.php | 4 +- cli/user-info.php | 12 +- composer.json | 10 +- composer.lock | 213 +++++++++++++-------- lib/Minz/Configuration.php | 28 +-- lib/Minz/ConfigurationSetterInterface.php | 19 ++ lib/Minz/Dispatcher.php | 25 ++- lib/Minz/Error.php | 2 +- lib/Minz/Extension.php | 8 +- lib/Minz/ExtensionManager.php | 2 +- lib/Minz/FrontController.php | 6 +- lib/Minz/Mailer.php | 5 +- lib/Minz/Migrator.php | 9 +- lib/Minz/ModelArray.php | 2 +- lib/Minz/ModelPdo.php | 2 +- lib/Minz/Paginator.php | 58 +++--- lib/Minz/Request.php | 4 +- lib/Minz/Translate.php | 7 +- lib/Minz/Url.php | 31 ++- lib/Minz/View.php | 11 +- lib/lib_date.php | 4 +- lib/lib_install.php | 12 +- lib/lib_rss.php | 41 ++-- p/api/fever.php | 15 +- p/f.php | 6 +- p/i/index.php | 4 +- phpstan.neon | 11 +- tests/app/Models/CategoryTest.php | 11 +- tests/app/Models/LogDAOTest.php | 2 +- tests/app/Models/SearchTest.php | 117 +++++------ tests/app/Models/UserQueryTest.php | 64 ++++--- tests/app/Utils/passwordUtilTest.php | 6 +- tests/cli/i18n/I18nCompletionValidatorTest.php | 13 +- tests/cli/i18n/I18nDataTest.php | 68 +++---- tests/cli/i18n/I18nFileTest.php | 5 +- tests/cli/i18n/I18nUsageValidatorTest.php | 15 +- tests/cli/i18n/I18nValueTest.php | 18 +- tests/fixtures/migrations/2019_12_22_FooBar.php | 4 +- tests/fixtures/migrations/2019_12_23_Baz.php | 4 +- .../migrations_with_failing/2020_01_11_FooBar.php | 4 +- .../migrations_with_failing/2020_01_12_Baz.php | 4 +- tests/lib/CssXPath/CssXPathTest.php | 2 +- tests/lib/Minz/MigratorTest.php | 46 ++--- tests/lib/PHPMailer/PHPMailerTest.php | 2 +- tests/phpstan-next.txt | 48 ++++- 100 files changed, 836 insertions(+), 719 deletions(-) create mode 100644 lib/Minz/ConfigurationSetterInterface.php diff --git a/app/Controllers/categoryController.php b/app/Controllers/categoryController.php index 91cd92787..0ca1bbbcd 100644 --- a/app/Controllers/categoryController.php +++ b/app/Controllers/categoryController.php @@ -33,7 +33,7 @@ class FreshRSS_category_Controller extends FreshRSS_ActionController { $url_redirect = array('c' => 'subscription', 'a' => 'add'); $limits = FreshRSS_Context::$system_conf->limits; - $this->view->categories = $catDAO->listCategories(false); + $this->view->categories = $catDAO->listCategories(false) ?: []; if (count($this->view->categories) >= $limits['max_categories']) { Minz_Request::bad(_t('feedback.sub.category.over_max', $limits['max_categories']), $url_redirect); @@ -231,7 +231,7 @@ class FreshRSS_category_Controller extends FreshRSS_ActionController { if (Minz_Request::paramBoolean('ajax')) { Minz_Request::setGoodNotification(_t('feedback.sub.category.updated')); - $this->view->_layout(false); + $this->view->_layout(null); } else { if ($ok) { Minz_Request::good(_t('feedback.sub.category.updated'), $url_redirect); diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index 667c2da74..87d9e4426 100644 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -264,7 +264,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { FreshRSS_Context::$user_conf->volatile = $volatile; $entryDAO = FreshRSS_Factory::createEntryDao(); - $this->view->nb_total = $entryDAO->count(); + $this->view->nb_total = $entryDAO->count() ?: 0; $databaseDAO = FreshRSS_Factory::createDatabaseDAO(); $this->view->size_user = $databaseDAO->size(); @@ -338,7 +338,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { * applied to the selected query. */ public function queryAction(): void { - $this->view->_layout(false); + $this->view->_layout(null); $id = Minz_Request::paramInt('id'); if ($id !== 0 || !isset(FreshRSS_Context::$user_conf->queries[$id])) { diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php index 7a30f94de..ff995b12f 100644 --- a/app/Controllers/entryController.php +++ b/app/Controllers/entryController.php @@ -24,7 +24,7 @@ class FreshRSS_entry_Controller extends FreshRSS_ActionController { // If ajax request, we do not print layout $this->ajax = Minz_Request::paramBoolean('ajax'); if ($this->ajax) { - $this->view->_layout(false); + $this->view->_layout(null); Minz_Request::_param('ajax'); } } @@ -107,7 +107,7 @@ class FreshRSS_entry_Controller extends FreshRSS_ActionController { $ids = is_array($id) ? $id : array($id); $entryDAO->markRead($ids, $is_read); $tagDAO = FreshRSS_Factory::createTagDao(); - $tagsForEntries = $tagDAO->getTagsForEntries($ids); + $tagsForEntries = $tagDAO->getTagsForEntries($ids) ?: []; $tags = array(); foreach ($tagsForEntries as $line) { $tags['t_' . $line['id_tag']][] = $line['id_entry']; diff --git a/app/Controllers/extensionController.php b/app/Controllers/extensionController.php index b482b1a35..4b440327d 100644 --- a/app/Controllers/extensionController.php +++ b/app/Controllers/extensionController.php @@ -79,7 +79,7 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController { */ public function configureAction(): void { if (Minz_Request::paramBoolean('ajax')) { - $this->view->_layout(false); + $this->view->_layout(null); } else { $this->indexAction(); $this->view->_path('extension/index.phtml'); @@ -143,7 +143,7 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController { if ($conf !== null && $res === true) { $ext_list = $conf->extensions_enabled; - $ext_list = array_filter($ext_list, function($key) use($type) { + $ext_list = array_filter($ext_list, static function(string $key) use($type) { // Remove from list the extensions that have disappeared or changed type $extension = Minz_ExtensionManager::findExtension($key); return $extension !== null && $extension->getType() === $type; @@ -205,7 +205,7 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController { if ($conf !== null && $res === true) { $ext_list = $conf->extensions_enabled; - $ext_list = array_filter($ext_list, function($key) use($type) { + $ext_list = array_filter($ext_list, static function(string $key) use($type) { // Remove from list the extensions that have disappeared or changed type $extension = Minz_ExtensionManager::findExtension($key); return $extension !== null && $extension->getType() === $type; diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 39a1c7289..15bf0128b 100644 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -262,7 +262,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController { FreshRSS_View::prependTitle(_t('sub.feed.title_add') . ' · '); $catDAO = FreshRSS_Factory::createCategoryDao(); - $this->view->categories = $catDAO->listCategories(false); + $this->view->categories = $catDAO->listCategories(false) ?: []; $this->view->feed = new FreshRSS_Feed($url); try { // We try to get more information about the feed. @@ -316,7 +316,8 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController { /** * @return array{0:int,1:FreshRSS_Feed|false,2:int} */ - public static function actualizeFeed(int $feed_id, string $feed_url, bool $force, ?SimplePie $simplePiePush = null, bool $noCommit = false, int $maxFeeds = 10) { + public static function actualizeFeed(int $feed_id, string $feed_url, bool $force, ?SimplePie $simplePiePush = null, + bool $noCommit = false, int $maxFeeds = 10): array { @set_time_limit(300); $feedDAO = FreshRSS_Factory::createFeedDao(); @@ -666,7 +667,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController { // are several updated feeds. Minz_Request::setGoodNotification(_t('feedback.sub.feed.actualizeds')); // No layout in ajax request. - $this->view->_layout(false); + $this->view->_layout(null); } else { // Redirect to the main page with correct notification. if ($updated_feeds === 1) { @@ -903,7 +904,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController { $this->view->selectorSuccess = false; $this->view->htmlContent = ''; - $this->view->_layout(false); + $this->view->_layout(null); $this->_csp([ 'default-src' => "'self'", diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php index 2df185398..4939a0748 100644 --- a/app/Controllers/importExportController.php +++ b/app/Controllers/importExportController.php @@ -226,7 +226,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController { unset($table['article']); for ($i = count($table['items']) - 1; $i >= 0; $i--) { $item = (array)($table['items'][$i]); - $item = array_filter($item, function ($v) { + $item = array_filter($item, static function ($v) { // Filter out empty properties, potentially reported as empty objects return (is_string($v) && trim($v) !== '') || !empty($v); }); @@ -267,7 +267,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController { * * $article_file the JSON file content. * true if articles from the file must be starred. - * @return boolean false if an error occurred, true otherwise. + * @return bool false if an error occurred, true otherwise. */ private function importJson(string $article_file, bool $starred = false): bool { $article_object = json_decode($article_file, true); @@ -575,10 +575,8 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController { * - export_starred (default: false) * - export_labelled (default: false) * - export_feeds (default: array()) a list of feed ids - * - * @return void|null */ - public function exportAction() { + public function exportAction(): void { if (!Minz_Request::isPost()) { Minz_Request::forward(['c' => 'importExport', 'a' => 'index'], true); return; @@ -654,7 +652,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController { header('Content-Type: ' . $content_type); header('Content-disposition: attachment; filename="' . $filename . '"'); - $this->view->_layout(false); + $this->view->_layout(null); $this->view->content = $content; } diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index 17aee3585..64371c530 100644 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -58,10 +58,10 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController { FreshRSS_Context::$id_max = time() . '000000'; - $this->view->callbackBeforeFeeds = function ($view) { + $this->view->callbackBeforeFeeds = function (FreshRSS_View $view) { try { $tagDAO = FreshRSS_Factory::createTagDao(); - $view->tags = $tagDAO->listTags(true); + $view->tags = $tagDAO->listTags(true) ?: []; $view->nbUnreadTags = 0; foreach ($view->tags as $tag) { $view->nbUnreadTags += $tag->nbUnread(); @@ -71,7 +71,7 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController { } }; - $this->view->callbackBeforeEntries = function ($view) { + $this->view->callbackBeforeEntries = function (FreshRSS_View $view) { try { FreshRSS_Context::$number++; //+1 for articles' page $view->entries = FreshRSS_index_Controller::listEntriesByContext(); @@ -83,7 +83,7 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController { } }; - $this->view->callbackBeforePagination = function ($view, $nbEntries, $lastEntry) { + $this->view->callbackBeforePagination = function (?FreshRSS_View $view, int $nbEntries, FreshRSS_Entry $lastEntry) { if ($nbEntries >= FreshRSS_Context::$number) { //We have enough entries: we discard the last one to use it for the next articles' page ob_clean(); @@ -170,7 +170,7 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController { // No layout for RSS output. $this->view->rss_url = PUBLIC_TO_INDEX_PATH . '/' . (empty($_SERVER['QUERY_STRING']) ? '' : '?' . $_SERVER['QUERY_STRING']); $this->view->rss_title = FreshRSS_Context::$name . ' | ' . FreshRSS_View::title(); - $this->view->_layout(false); + $this->view->_layout(null); header('Content-Type: application/rss+xml; charset=utf-8'); } @@ -238,7 +238,7 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController { } // No layout for OPML output. - $this->view->_layout(false); + $this->view->_layout(null); header('Content-Type: application/xml; charset=utf-8'); } diff --git a/app/Controllers/javascriptController.php b/app/Controllers/javascriptController.php index d7c600113..ce25d03c9 100644 --- a/app/Controllers/javascriptController.php +++ b/app/Controllers/javascriptController.php @@ -3,7 +3,7 @@ class FreshRSS_javascript_Controller extends FreshRSS_ActionController { public function firstAction(): void { - $this->view->_layout(false); + $this->view->_layout(null); } public function actualizeAction(): void { @@ -20,9 +20,9 @@ class FreshRSS_javascript_Controller extends FreshRSS_ActionController { public function nbUnreadsPerFeedAction(): void { header('Content-Type: application/json; charset=UTF-8'); $catDAO = FreshRSS_Factory::createCategoryDao(); - $this->view->categories = $catDAO->listCategories(true, false); + $this->view->categories = $catDAO->listCategories(true, false) ?: []; $tagDAO = FreshRSS_Factory::createTagDao(); - $this->view->tags = $tagDAO->listTags(true); + $this->view->tags = $tagDAO->listTags(true) ?: []; } //For Web-form login diff --git a/app/Controllers/statsController.php b/app/Controllers/statsController.php index cd9a247c4..0fc6490f8 100644 --- a/app/Controllers/statsController.php +++ b/app/Controllers/statsController.php @@ -26,7 +26,7 @@ class FreshRSS_stats_Controller extends FreshRSS_ActionController { $catDAO->checkDefault(); $feedDAO->updateTTL(); - $this->view->categories = $catDAO->listSortedCategories(false); + $this->view->categories = $catDAO->listSortedCategories(false) ?: []; $this->view->default_category = $catDAO->getDefault(); FreshRSS_View::prependTitle(_t('admin.stats.title') . ' · '); @@ -207,7 +207,7 @@ class FreshRSS_stats_Controller extends FreshRSS_ActionController { $id = null; } - $this->view->categories = $categoryDAO->listCategories(); + $this->view->categories = $categoryDAO->listCategories() ?: []; $this->view->feed = $id === null ? null : $feedDAO->searchById($id); $this->view->days = $statsDAO->getDays(); $this->view->months = $statsDAO->getMonths(); diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index e0a8d4ff4..d96cb02e1 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -19,7 +19,7 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController { $catDAO->checkDefault(); $feedDAO->updateTTL(); - $this->view->categories = $catDAO->listSortedCategories(false, true); + $this->view->categories = $catDAO->listSortedCategories(false, true) ?: []; $this->view->default_category = $catDAO->getDefault(); $signalError = false; @@ -90,7 +90,7 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController { */ public function feedAction(): void { if (Minz_Request::paramBoolean('ajax')) { - $this->view->_layout(false); + $this->view->_layout(null); } else { FreshRSS_View::appendScript(Minz_Url::display('/scripts/feed.js?' . @filemtime(PUBLIC_PATH . '/scripts/feed.js'))); } @@ -200,7 +200,7 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController { ]); } - $feed->_filtersAction('read', preg_split('/[\n\r]+/', Minz_Request::paramString('filteractions_read'))); + $feed->_filtersAction('read', preg_split('/[\n\r]+/', Minz_Request::paramString('filteractions_read')) ?: []); $feed->_kind(Minz_Request::paramInt('feed_kind') ?: FreshRSS_Feed::KIND_RSS); if ($feed->kind() === FreshRSS_Feed::KIND_HTML_XPATH || $feed->kind() === FreshRSS_Feed::KIND_XML_XPATH) { @@ -235,8 +235,8 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController { 'name' => Minz_Request::paramString('name'), 'kind' => $feed->kind(), 'description' => sanitizeHTML(Minz_Request::paramString('description', true)), - 'website' => checkUrl(Minz_Request::paramString('website')), - 'url' => checkUrl(Minz_Request::paramString('url')), + 'website' => checkUrl(Minz_Request::paramString('website')) ?: '', + 'url' => checkUrl(Minz_Request::paramString('url')) ?: '', 'category' => Minz_Request::paramInt('category'), 'pathEntries' => Minz_Request::paramString('path_entries'), 'priority' => Minz_Request::paramTernary('priority') === null ? FreshRSS_Feed::PRIORITY_MAIN_STREAM : Minz_Request::paramInt('priority'), @@ -283,7 +283,7 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController { } public function categoryAction(): void { - $this->view->_layout(false); + $this->view->_layout(null); $categoryDAO = FreshRSS_Factory::createCategoryDao(); diff --git a/app/Controllers/tagController.php b/app/Controllers/tagController.php index e4048238c..7a89b2b84 100644 --- a/app/Controllers/tagController.php +++ b/app/Controllers/tagController.php @@ -23,7 +23,7 @@ class FreshRSS_tag_Controller extends FreshRSS_ActionController { // If ajax request, we do not print layout $this->ajax = Minz_Request::paramBoolean('ajax'); if ($this->ajax) { - $this->view->_layout(false); + $this->view->_layout(null); Minz_Request::_param('ajax'); } } @@ -39,7 +39,7 @@ class FreshRSS_tag_Controller extends FreshRSS_ActionController { $checked = Minz_Request::paramTernary('checked'); if ($id_entry != '') { $tagDAO = FreshRSS_Factory::createTagDao(); - if ($id_tag === 0 && $name_tag !== '' && $checked) { + if ($id_tag == 0 && $name_tag !== '' && $checked) { if ($existing_tag = $tagDAO->searchByName($name_tag)) { // Use existing tag $tagDAO->tagEntry($existing_tag->id(), $id_entry, $checked); @@ -48,7 +48,7 @@ class FreshRSS_tag_Controller extends FreshRSS_ActionController { $id_tag = $tagDAO->addTag(array('name' => $name_tag)); } } - if ($id_tag !== 0) { + if ($id_tag != false) { $tagDAO->tagEntry($id_tag, $id_entry, $checked); } } @@ -82,12 +82,12 @@ class FreshRSS_tag_Controller extends FreshRSS_ActionController { } public function getTagsForEntryAction(): void { - $this->view->_layout(false); + $this->view->_layout(null); header('Content-Type: application/json; charset=UTF-8'); header('Cache-Control: private, no-cache, no-store, must-revalidate'); $id_entry = Minz_Request::paramString('id_entry'); $tagDAO = FreshRSS_Factory::createTagDao(); - $this->view->tagsForEntry = $tagDAO->getTagsForEntry($id_entry); + $this->view->tagsForEntry = $tagDAO->getTagsForEntry($id_entry) ?: []; } public function addAction(): void { @@ -110,11 +110,10 @@ class FreshRSS_tag_Controller extends FreshRSS_ActionController { } /** - * @return void|null * @throws Minz_ConfigurationNamespaceException * @throws Minz_PDOConnectionException */ - public function renameAction() { + public function renameAction(): void { if (!Minz_Request::isPost()) { Minz_Error::error(405); } @@ -145,6 +144,6 @@ class FreshRSS_tag_Controller extends FreshRSS_ActionController { public function indexAction(): void { $tagDAO = FreshRSS_Factory::createTagDao(); - $this->view->tags = $tagDAO->listTags(); + $this->view->tags = $tagDAO->listTags() ?: []; } } diff --git a/app/Models/Auth.php b/app/Models/Auth.php index 8fd06b24d..e868e1b4f 100644 --- a/app/Models/Auth.php +++ b/app/Models/Auth.php @@ -135,9 +135,9 @@ class FreshRSS_Auth { * Returns if current user has access to the given scope. * * @param string $scope general (default) or admin - * @return boolean true if user has corresponding access, false else. + * @return bool true if user has corresponding access, false else. */ - public static function hasAccess($scope = 'general'): bool { + public static function hasAccess(string $scope = 'general'): bool { if (FreshRSS_Context::$user_conf == null) { return false; } @@ -154,7 +154,7 @@ class FreshRSS_Auth { default: $ok = false; } - return $ok; + return (bool)$ok; } /** diff --git a/app/Models/BooleanSearch.php b/app/Models/BooleanSearch.php index 89e6e3ee2..f4979b22b 100644 --- a/app/Models/BooleanSearch.php +++ b/app/Models/BooleanSearch.php @@ -230,7 +230,7 @@ class FreshRSS_BooleanSearch { if ($input == '') { return; } - $splits = preg_split('/\b(OR)\b/i', $input, -1, PREG_SPLIT_DELIM_CAPTURE); + $splits = preg_split('/\b(OR)\b/i', $input, -1, PREG_SPLIT_DELIM_CAPTURE) ?: []; $segment = ''; $ns = count($splits); diff --git a/app/Models/Category.php b/app/Models/Category.php index 737544481..4e28b1741 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -262,7 +262,7 @@ class FreshRSS_Category extends Minz_Model { $catDAO = FreshRSS_Factory::createCategoryDao(); $catDAO->updateLastUpdate($this->id(), !$ok); - return $ok; + return (bool)$ok; } private function sortFeeds(): void { diff --git a/app/Models/CategoryDAO.php b/app/Models/CategoryDAO.php index 64b14ffb7..29593ce5f 100644 --- a/app/Models/CategoryDAO.php +++ b/app/Models/CategoryDAO.php @@ -477,7 +477,7 @@ SQL; $cat->_id($previousLine['c_id']); $cat->_kind($previousLine['c_kind']); $cat->_lastUpdate($previousLine['c_last_update'] ?? 0); - $cat->_error($previousLine['c_error'] ?? false); + $cat->_error($previousLine['c_error'] ?? 0); $cat->_attributes('', $previousLine['c_attributes']); $list[$previousLine['c_id']] = $cat; } diff --git a/app/Models/Context.php b/app/Models/Context.php index b2631291a..03006cbbf 100644 --- a/app/Models/Context.php +++ b/app/Models/Context.php @@ -110,10 +110,9 @@ final class FreshRSS_Context { /** * Initialize the context for the current user. - * @return FreshRSS_UserConfiguration|false * @throws Minz_ConfigurationParamException */ - public static function initUser(string $username = '', bool $userMustExist = true) { + public static function initUser(string $username = '', bool $userMustExist = true): ?FreshRSS_UserConfiguration { FreshRSS_Context::$user_conf = null; if (!isset($_SESSION)) { Minz_Session::init('FreshRSS'); @@ -145,7 +144,7 @@ final class FreshRSS_Context { Minz_Session::unlock(); if (FreshRSS_Context::$user_conf == null) { - return false; + return null; } FreshRSS_Context::$search = new FreshRSS_BooleanSearch(''); @@ -249,8 +248,8 @@ final class FreshRSS_Context { /** * Return the current get as a string or an array. * - * If $array is true, the first item of the returned value is 'f' or 'c' and - * the second is the id. + * If $array is true, the first item of the returned value is 'f' or 'c' or 't' and the second is the id. + * @phpstan-return ($asArray is true ? array{'c'|'f'|'t',bool|int} : string) * @return string|array{string,bool|int} */ public static function currentGet(bool $asArray = false) { diff --git a/app/Models/DatabaseDAO.php b/app/Models/DatabaseDAO.php index 28dd36cd9..aeac6f435 100644 --- a/app/Models/DatabaseDAO.php +++ b/app/Models/DatabaseDAO.php @@ -79,7 +79,7 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { $ok &= in_array($c['name'], $schema); } - return $ok; + return (bool)$ok; } public function categoryIsCorrect(): bool { diff --git a/app/Models/DatabaseDAOSQLite.php b/app/Models/DatabaseDAOSQLite.php index 3fab1134d..0909613a7 100644 --- a/app/Models/DatabaseDAOSQLite.php +++ b/app/Models/DatabaseDAOSQLite.php @@ -8,7 +8,10 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO { public function tablesAreCorrect(): bool { $sql = 'SELECT name FROM sqlite_master WHERE type="table"'; $stm = $this->pdo->query($sql); - $res = $stm->fetchAll(PDO::FETCH_ASSOC); + $res = $stm ? $stm->fetchAll(PDO::FETCH_ASSOC) : false; + if ($res === false) { + return false; + } $tables = array( $this->pdo->prefix() . 'category' => false, @@ -29,7 +32,7 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO { public function getSchema(string $table): array { $sql = 'PRAGMA table_info(' . $table . ')'; $stm = $this->pdo->query($sql); - return $this->listDaoToSchema($stm->fetchAll(PDO::FETCH_ASSOC)); + return $stm ? $this->listDaoToSchema($stm->fetchAll(PDO::FETCH_ASSOC) ?: []) : []; } public function entryIsCorrect(): bool { @@ -62,7 +65,7 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO { public function size(bool $all = false): int { $sum = 0; if ($all) { - foreach (glob(DATA_PATH . '/users/*/db.sqlite') as $filename) { + foreach (glob(DATA_PATH . '/users/*/db.sqlite') ?: [] as $filename) { $sum += @filesize($filename); } } else { diff --git a/app/Models/Entry.php b/app/Models/Entry.php index d208b07ec..20f17d1c7 100644 --- a/app/Models/Entry.php +++ b/app/Models/Entry.php @@ -106,7 +106,7 @@ class FreshRSS_Entry extends Minz_Model { return $this->authors(true); } /** - * @phpstan return ($asString ? string : array) + * @phpstan-return ($asString is true ? string : array) * @return string|array */ public function authors(bool $asString = false) { @@ -285,7 +285,7 @@ HTML; /** * @return array|null */ - public function thumbnail(bool $searchEnclosures = true) { + public function thumbnail(bool $searchEnclosures = true): ?array { $thumbnail = $this->attributes('thumbnail'); if (!empty($thumbnail['url'])) { return $thumbnail; @@ -352,7 +352,10 @@ HTML; return $this->feedId; } - /** @return string|array */ + /** + * @phpstan-return ($asString is true ? string : array) + * @return string|array + */ public function tags(bool $asString = false) { if ($asString) { return $this->tags == null ? '' : '#' . implode(' #', $this->tags); @@ -609,7 +612,7 @@ HTML; } } } - return $ok; + return (bool)$ok; } /** @param array $titlesAsRead */ diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 9f24beb7c..1661bfd13 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -308,7 +308,7 @@ SQL; * there is an other way to do that. * * @param string|array $ids - * @return false|integer + * @return int|false */ public function markFavorite($ids, bool $is_favorite = true) { if (!is_array($ids)) { @@ -348,12 +348,8 @@ SQL; * feeds from one category or on all feeds. * * @todo It can use the query builder refactoring to build that query - * - * @param false|integer $catId category ID - * @param false|integer $feedId feed ID - * @return boolean */ - protected function updateCacheUnreads($catId = false, $feedId = false) { + protected function updateCacheUnreads(?int $catId = null, ?int $feedId = null): bool { $sql = 'UPDATE `_feed` f ' . 'LEFT OUTER JOIN (' . 'SELECT e.id_feed, ' @@ -365,13 +361,13 @@ SQL; . 'SET f.`cache_nbUnreads`=COALESCE(x.nbUnreads, 0)'; $hasWhere = false; $values = array(); - if ($feedId !== false) { + if ($feedId != null) { $sql .= ' WHERE'; $hasWhere = true; $sql .= ' f.id=?'; $values[] = $feedId; } - if ($catId !== false) { + if ($catId != null) { $sql .= $hasWhere ? ' AND' : ' WHERE'; $hasWhere = true; $sql .= ' f.category=?'; @@ -397,8 +393,8 @@ SQL; * same if it is an array or not. * * @param string|array $ids - * @param boolean $is_read - * @return integer|false affected rows + * @param bool $is_read + * @return int|false affected rows */ public function markRead($ids, bool $is_read = true) { FreshRSS_UserDAO::touch(); @@ -431,7 +427,7 @@ SQL; return false; } $affected = $stm->rowCount(); - if (($affected > 0) && (!$this->updateCacheUnreads(false, false))) { + if (($affected > 0) && (!$this->updateCacheUnreads(null, null))) { return false; } return $affected; @@ -469,7 +465,7 @@ SQL; * separated. * * @param string $idMax fail safe article ID - * @return integer|false affected rows + * @return int|false affected rows */ public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false, int $priorityMin = 0, ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { @@ -498,7 +494,7 @@ SQL; return false; } $affected = $stm->rowCount(); - if (($affected > 0) && (!$this->updateCacheUnreads(false, false))) { + if (($affected > 0) && (!$this->updateCacheUnreads(null, null))) { return false; } return $affected; @@ -511,9 +507,9 @@ SQL; * * If $idMax equals 0, a deprecated debug message is logged * - * @param integer $id category ID + * @param int $id category ID * @param string $idMax fail safe article ID - * @return integer|false affected rows + * @return int|false affected rows */ public function markReadCat(int $id, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); @@ -536,7 +532,7 @@ SQL; return false; } $affected = $stm->rowCount(); - if (($affected > 0) && (!$this->updateCacheUnreads($id, false))) { + if (($affected > 0) && (!$this->updateCacheUnreads($id, null))) { return false; } return $affected; @@ -549,9 +545,9 @@ SQL; * * If $idMax equals 0, a deprecated debug message is logged * - * @param integer $id_feed feed ID + * @param int $id_feed feed ID * @param string $idMax fail safe article ID - * @return integer|false affected rows + * @return int|false affected rows */ public function markReadFeed(int $id_feed, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); @@ -597,9 +593,9 @@ SQL; /** * Mark all the articles in a tag as read. - * @param integer $id tag ID, or empty for targeting any tag + * @param int $id tag ID, or empty for targeting any tag * @param string $idMax max article ID - * @return integer|false affected rows + * @return int|false affected rows */ public function markReadTag(int $id = 0, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { @@ -630,7 +626,7 @@ SQL; return false; } $affected = $stm->rowCount(); - if (($affected > 0) && (!$this->updateCacheUnreads(false, false))) { + if (($affected > 0) && (!$this->updateCacheUnreads(null, null))) { return false; } return $affected; @@ -758,7 +754,7 @@ SQL; } /** @return array{0:array,1:string} */ - public static function sqlBooleanSearch(string $alias, FreshRSS_BooleanSearch $filters, int $level = 0) { + public static function sqlBooleanSearch(string $alias, FreshRSS_BooleanSearch $filters, int $level = 0): array { $search = ''; $values = []; diff --git a/app/Models/EntryDAOSQLite.php b/app/Models/EntryDAOSQLite.php index e509097f2..c86791372 100644 --- a/app/Models/EntryDAOSQLite.php +++ b/app/Models/EntryDAOSQLite.php @@ -25,7 +25,7 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { /** @param array $errorInfo */ protected function autoUpdateDb(array $errorInfo): bool { if ($tableInfo = $this->pdo->query("PRAGMA table_info('entry')")) { - $columns = $tableInfo->fetchAll(PDO::FETCH_COLUMN, 1); + $columns = $tableInfo->fetchAll(PDO::FETCH_COLUMN, 1) ?: []; foreach (['attributes'] as $column) { if (!in_array($column, $columns)) { return $this->addColumn($column); @@ -34,14 +34,14 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { } if ($tableInfo = $this->pdo->query("SELECT sql FROM sqlite_master where name='tag'")) { $showCreate = $tableInfo->fetchColumn(); - if (stripos($showCreate, 'tag') === false) { + if (is_string($showCreate) && stripos($showCreate, 'tag') === false) { $tagDAO = FreshRSS_Factory::createTagDao(); return $tagDAO->createTagTable(); //v1.12.0 } } if ($tableInfo = $this->pdo->query("SELECT sql FROM sqlite_master where name='entrytmp'")) { $showCreate = $tableInfo->fetchColumn(); - if (stripos($showCreate, 'entrytmp') === false) { + if (is_string($showCreate) && stripos($showCreate, 'entrytmp') === false) { return $this->createEntryTempTable(); //v1.7.0 } } @@ -78,20 +78,20 @@ DROP TABLE IF EXISTS `tmp`; return $result; } - protected function updateCacheUnreads($catId = false, $feedId = false) { + protected function updateCacheUnreads(?int $catId = null, ?int $feedId = null): bool { $sql = 'UPDATE `_feed` ' . 'SET `cache_nbUnreads`=(' . 'SELECT COUNT(*) AS nbUnreads FROM `_entry` e ' . 'WHERE e.id_feed=`_feed`.id AND e.is_read=0)'; $hasWhere = false; $values = array(); - if ($feedId !== false) { + if ($feedId != null) { $sql .= ' WHERE'; $hasWhere = true; $sql .= ' id=?'; $values[] = $feedId; } - if ($catId !== false) { + if ($catId != null) { $sql .= $hasWhere ? ' AND' : ' WHERE'; $hasWhere = true; $sql .= ' category=?'; @@ -117,8 +117,8 @@ DROP TABLE IF EXISTS `tmp`; * same if it is an array or not. * * @param string|array $ids - * @param boolean $is_read - * @return integer|false affected rows + * @param bool $is_read + * @return int|false affected rows */ public function markRead($ids, bool $is_read = true) { FreshRSS_UserDAO::touch(); @@ -176,9 +176,9 @@ DROP TABLE IF EXISTS `tmp`; * separated. * * @param string $idMax fail safe article ID - * @param boolean $onlyFavorites - * @param integer $priorityMin - * @return integer|false affected rows + * @param bool $onlyFavorites + * @param int $priorityMin + * @return int|false affected rows */ public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false, int $priorityMin = 0, ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { @@ -205,7 +205,7 @@ DROP TABLE IF EXISTS `tmp`; return false; } $affected = $stm->rowCount(); - if (($affected > 0) && (!$this->updateCacheUnreads(false, false))) { + if (($affected > 0) && (!$this->updateCacheUnreads(null, null))) { return false; } return $affected; @@ -218,9 +218,9 @@ DROP TABLE IF EXISTS `tmp`; * * If $idMax equals 0, a deprecated debug message is logged * - * @param integer $id category ID + * @param int $id category ID * @param string $idMax fail safe article ID - * @return integer|false affected rows + * @return int|false affected rows */ public function markReadCat(int $id, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); @@ -244,7 +244,7 @@ DROP TABLE IF EXISTS `tmp`; return false; } $affected = $stm->rowCount(); - if (($affected > 0) && (!$this->updateCacheUnreads($id, false))) { + if (($affected > 0) && (!$this->updateCacheUnreads($id, null))) { return false; } return $affected; @@ -252,9 +252,9 @@ DROP TABLE IF EXISTS `tmp`; /** * Mark all the articles in a tag as read. - * @param integer $id tag ID, or empty for targeting any tag + * @param int $id tag ID, or empty for targeting any tag * @param string $idMax max article ID - * @return integer|false affected rows + * @return int|false affected rows */ public function markReadTag($id = 0, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); @@ -283,7 +283,7 @@ DROP TABLE IF EXISTS `tmp`; return false; } $affected = $stm->rowCount(); - if (($affected > 0) && (!$this->updateCacheUnreads(false, false))) { + if (($affected > 0) && (!$this->updateCacheUnreads(null, null))) { return false; } return $affected; diff --git a/app/Models/Factory.php b/app/Models/Factory.php index 80c611db5..d06c3c63d 100644 --- a/app/Models/Factory.php +++ b/app/Models/Factory.php @@ -13,7 +13,7 @@ class FreshRSS_Factory { * @throws Minz_ConfigurationNamespaceException|Minz_PDOConnectionException */ public static function createCategoryDao(?string $username = null): FreshRSS_CategoryDAO { - switch (FreshRSS_Context::$system_conf->db['type']) { + switch (FreshRSS_Context::$system_conf->db['type'] ?? '') { case 'sqlite': return new FreshRSS_CategoryDAOSQLite($username); default: @@ -25,7 +25,7 @@ class FreshRSS_Factory { * @throws Minz_ConfigurationNamespaceException|Minz_PDOConnectionException */ public static function createFeedDao(?string $username = null): FreshRSS_FeedDAO { - switch (FreshRSS_Context::$system_conf->db['type']) { + switch (FreshRSS_Context::$system_conf->db['type'] ?? '') { case 'sqlite': return new FreshRSS_FeedDAOSQLite($username); default: @@ -37,7 +37,7 @@ class FreshRSS_Factory { * @throws Minz_ConfigurationNamespaceException|Minz_PDOConnectionException */ public static function createEntryDao(?string $username = null): FreshRSS_EntryDAO { - switch (FreshRSS_Context::$system_conf->db['type']) { + switch (FreshRSS_Context::$system_conf->db['type'] ?? '') { case 'sqlite': return new FreshRSS_EntryDAOSQLite($username); case 'pgsql': @@ -51,7 +51,7 @@ class FreshRSS_Factory { * @throws Minz_ConfigurationNamespaceException|Minz_PDOConnectionException */ public static function createTagDao(?string $username = null): FreshRSS_TagDAO { - switch (FreshRSS_Context::$system_conf->db['type']) { + switch (FreshRSS_Context::$system_conf->db['type'] ?? '') { case 'sqlite': return new FreshRSS_TagDAOSQLite($username); case 'pgsql': @@ -65,7 +65,7 @@ class FreshRSS_Factory { * @throws Minz_ConfigurationNamespaceException|Minz_PDOConnectionException */ public static function createStatsDAO(?string $username = null): FreshRSS_StatsDAO { - switch (FreshRSS_Context::$system_conf->db['type']) { + switch (FreshRSS_Context::$system_conf->db['type'] ?? '') { case 'sqlite': return new FreshRSS_StatsDAOSQLite($username); case 'pgsql': @@ -79,7 +79,7 @@ class FreshRSS_Factory { * @throws Minz_ConfigurationNamespaceException|Minz_PDOConnectionException */ public static function createDatabaseDAO(?string $username = null): FreshRSS_DatabaseDAO { - switch (FreshRSS_Context::$system_conf->db['type']) { + switch (FreshRSS_Context::$system_conf->db['type'] ?? '') { case 'sqlite': return new FreshRSS_DatabaseDAOSQLite($username); case 'pgsql': diff --git a/app/Models/Feed.php b/app/Models/Feed.php index 447445d46..ecf875723 100644 --- a/app/Models/Feed.php +++ b/app/Models/Feed.php @@ -71,6 +71,7 @@ class FreshRSS_Feed extends Minz_Model { private $error = false; /** @var int */ private $ttl = self::TTL_DEFAULT; + /** @var array */ private $attributes = []; /** @var bool */ private $mute = false; @@ -93,10 +94,7 @@ class FreshRSS_Feed extends Minz_Model { } } - /** - * @return FreshRSS_Feed - */ - public static function example() { + public static function example(): FreshRSS_Feed { $f = new FreshRSS_Feed('http://example.net/', false); $f->faviconPrepare(); return $f; @@ -142,12 +140,16 @@ class FreshRSS_Feed extends Minz_Model { return $this->categoryId; } - public function entries() { + /** + * @return array|null + * @deprecated + */ + public function entries(): ?array { Minz_Log::warning(__method__ . ' is deprecated since FreshRSS 1.16.1!'); $simplePie = $this->load(false, true); return $simplePie == null ? [] : iterator_to_array($this->loadEntries($simplePie)); } - public function name($raw = false): string { + public function name(bool $raw = false): string { return $raw || $this->name != '' ? $this->name : preg_replace('%^https?://(www[.])?%i', '', $this->url); } /** @return string HTML-encoded URL of the Web site of the feed */ @@ -167,7 +169,11 @@ class FreshRSS_Feed extends Minz_Model { public function pathEntries(): string { return $this->pathEntries; } - public function httpAuth($raw = true) { + /** + * @phpstan-return ($raw is true ? string : array{'username':string,'password':string}) + * @return array{'username':string,'password':string}|string + */ + public function httpAuth(bool $raw = true) { if ($raw) { return $this->httpAuth; } else { @@ -223,7 +229,7 @@ class FreshRSS_Feed extends Minz_Model { return $this->nbEntries; } - public function nbNotRead($includePending = false): int { + public function nbNotRead(bool $includePending = false): int { if ($this->nbNotRead < 0) { $feedDAO = FreshRSS_Factory::createFeedDao(); $this->nbNotRead = $feedDAO->countNotRead($this->id()); @@ -231,7 +237,7 @@ class FreshRSS_Feed extends Minz_Model { return $this->nbNotRead + ($includePending ? $this->nbPendingNotRead : 0); } - public function faviconPrepare() { + public function faviconPrepare(): void { require_once(LIB_PATH . '/favicons.php'); $url = $this->website; if ($url == '') { @@ -253,7 +259,7 @@ class FreshRSS_Feed extends Minz_Model { } } } - public static function faviconDelete($hash) { + public static function faviconDelete(string $hash): void { $path = DATA_PATH . '/favicons/' . $hash; @unlink($path . '.ico'); @unlink($path . '.txt'); @@ -262,10 +268,11 @@ class FreshRSS_Feed extends Minz_Model { return Minz_Url::display('/f.php?' . $this->hash()); } - public function _id($value) { - $this->id = intval($value); + public function _id(int $value): void { + $this->id = $value; } - public function _url(string $value, bool $validate = true) { + + public function _url(string $value, bool $validate = true): void { $this->hash = ''; $url = $value; if ($validate) { @@ -276,26 +283,26 @@ class FreshRSS_Feed extends Minz_Model { } $this->url = $url; } - public function _kind(int $value) { + + public function _kind(int $value): void { $this->kind = $value; } - /** @param FreshRSS_Category|null $cat */ - public function _category($cat) { + public function _category(?FreshRSS_Category $cat): void { $this->category = $cat; $this->categoryId = $this->category == null ? 0 : $this->category->id(); } /** @param int|string $id */ - public function _categoryId($id) { + public function _categoryId($id): void { $this->category = null; $this->categoryId = intval($id); } - public function _name(string $value) { + public function _name(string $value): void { $this->name = $value == '' ? '' : trim($value); } - public function _website(string $value, bool $validate = true) { + public function _website(string $value, bool $validate = true): void { if ($validate) { $value = checkUrl($value); } @@ -304,37 +311,37 @@ class FreshRSS_Feed extends Minz_Model { } $this->website = $value; } - public function _description(string $value) { + public function _description(string $value): void { $this->description = $value == '' ? '' : $value; } - public function _lastUpdate($value) { - $this->lastUpdate = intval($value); + public function _lastUpdate(int $value): void { + $this->lastUpdate = $value; } - public function _priority($value) { - $this->priority = intval($value); + public function _priority(int $value): void { + $this->priority = $value; } /** @param string $value HTML-encoded CSS selector */ - public function _pathEntries(string $value) { + public function _pathEntries(string $value): void { $this->pathEntries = $value; } - public function _httpAuth(string $value) { + public function _httpAuth(string $value): void { $this->httpAuth = $value; } - public function _error($value) { + /** @param bool|int $value */ + public function _error($value): void { $this->error = (bool)$value; } - public function _mute(bool $value) { + public function _mute(bool $value): void { $this->mute = $value; } - public function _ttl($value) { - $value = intval($value); + public function _ttl(int $value): void { $value = min($value, 100000000); $this->ttl = abs($value); $this->mute = $value < self::TTL_DEFAULT; } /** @param string|array|bool|int|null $value Value, not HTML-encoded */ - public function _attributes(string $key, $value) { + public function _attributes(string $key, $value): void { if ($key == '') { if (is_string($value)) { $value = json_decode($value, true); @@ -349,17 +356,14 @@ class FreshRSS_Feed extends Minz_Model { } } - public function _nbNotRead($value) { - $this->nbNotRead = intval($value); + public function _nbNotRead(int $value): void { + $this->nbNotRead = $value; } - public function _nbEntries($value) { - $this->nbEntries = intval($value); + public function _nbEntries(int $value): void { + $this->nbEntries = $value; } - /** - * @return SimplePie|null - */ - public function load(bool $loadDetails = false, bool $noCache = false) { + public function load(bool $loadDetails = false, bool $noCache = false): ?SimplePie { if ($this->url != '') { // @phpstan-ignore-next-line if (CACHE_PATH === false) { @@ -440,7 +444,7 @@ class FreshRSS_Feed extends Minz_Model { /** * @return array */ - public function loadGuids(SimplePie $simplePie) { + public function loadGuids(SimplePie $simplePie): array { $hasUniqueGuids = true; $testGuids = []; $guids = []; @@ -474,6 +478,9 @@ class FreshRSS_Feed extends Minz_Model { return $guids; } + /** + * @return iterable + */ public function loadEntries(SimplePie $simplePie) { $hasBadGuids = $this->attributes('hasBadGuids'); @@ -591,10 +598,7 @@ class FreshRSS_Feed extends Minz_Model { } } - /** - * @return SimplePie|null - */ - public function loadHtmlXpath() { + public function loadHtmlXpath(): ?SimplePie { if ($this->url == '') { return null; } @@ -708,7 +712,7 @@ class FreshRSS_Feed extends Minz_Model { if ($item['title'] != '' || $item['content'] != '' || $item['link'] != '') { // HTML-encoding/escaping of the relevant fields (all except 'content') foreach (['author', 'categories', 'guid', 'link', 'thumbnail', 'timestamp', 'title'] as $key) { - if (!empty($item[$key])) { + if (!empty($item[$key]) && is_string($item[$key])) { $item[$key] = Minz_Helper::htmlspecialchars_utf8($item[$key]); } } @@ -731,7 +735,7 @@ class FreshRSS_Feed extends Minz_Model { /** * To keep track of some new potentially unread articles since last commit+fetch from database */ - public function incPendingUnread(int $n = 1) { + public function incPendingUnread(int $n = 1): void { $this->nbPendingNotRead += $n; } @@ -770,6 +774,7 @@ class FreshRSS_Feed extends Minz_Model { /** * Remember to call updateCachedValue($id_feed) or updateCachedValues() just after + * @return int|false */ public function cleanOldEntries() { $archiving = $this->attributes('archiving'); @@ -785,7 +790,6 @@ class FreshRSS_Feed extends Minz_Model { $entryDAO = FreshRSS_Factory::createEntryDao(); $nb = $entryDAO->cleanOldEntries($this->id(), $archiving); if ($nb > 0) { - $needFeedCacheRefresh = true; Minz_Log::debug($nb . ' entries cleaned in feed [' . $this->url(false) . '] with: ' . json_encode($archiving)); } return $nb; @@ -793,6 +797,7 @@ class FreshRSS_Feed extends Minz_Model { return false; } + /** @param array $attributes */ public static function cacheFilename(string $url, array $attributes, int $kind = FreshRSS_Feed::KIND_RSS): string { $simplePie = customSimplePie($attributes); $filename = $simplePie->get_cache_filename($url); @@ -851,12 +856,12 @@ class FreshRSS_Feed extends Minz_Model { } /** - * @param array $filterActions + * @param array|null $filterActions */ - private function _filterActions($filterActions) { + private function _filterActions(?array $filterActions): void { $this->filterActions = $filterActions; if (is_array($this->filterActions) && !empty($this->filterActions)) { - $this->_attributes('filters', array_map(function ($af) { + $this->_attributes('filters', array_map(static function (?FreshRSS_FilterAction $af) { return $af == null ? null : $af->toJSON(); }, $this->filterActions)); } else { @@ -885,10 +890,10 @@ class FreshRSS_Feed extends Minz_Model { /** * @param array $filters */ - public function _filtersAction(string $action, $filters) { + public function _filtersAction(string $action, array $filters): void { $action = trim($action); if ($action == '' || !is_array($filters)) { - return false; + return; } $filters = array_unique(array_map('trim', $filters)); $filterActions = $this->filterActions(); diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php index 9138f3d59..837fef7f1 100644 --- a/app/Models/FeedDAO.php +++ b/app/Models/FeedDAO.php @@ -268,7 +268,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo { * @param bool|null $muted to include only muted feeds * @return int|false */ - public function deleteFeedByCategory(int $id, $muted = null) { + public function deleteFeedByCategory(int $id, ?bool $muted = null) { $sql = 'DELETE FROM `_feed` WHERE category=?'; if ($muted) { $sql .= ' AND ttl < 0'; @@ -338,7 +338,7 @@ SQL; } /** @return array */ - public function listFeedsNewestItemUsec(?int $id_feed = null) { + public function listFeedsNewestItemUsec(?int $id_feed = null): array { $sql = 'SELECT id_feed, MAX(id) as newest_item_us FROM `_entry` '; if ($id_feed === null) { $sql .= 'GROUP BY id_feed'; @@ -358,7 +358,7 @@ SQL; * Use $defaultCacheDuration == -1 to return all feeds, without filtering them by TTL. * @return array */ - public function listFeedsOrderUpdate(int $defaultCacheDuration = 3600, int $limit = 0) { + public function listFeedsOrderUpdate(int $defaultCacheDuration = 3600, int $limit = 0): array { $this->updateTTL(); $sql = 'SELECT id, url, kind, name, website, `lastUpdate`, `pathEntries`, `httpAuth`, ttl, attributes ' . 'FROM `_feed` ' @@ -398,7 +398,7 @@ SQL; * @param bool|null $muted to include only muted feeds * @return array */ - public function listByCategory(int $cat, $muted = null): array { + public function listByCategory(int $cat, ?bool $muted = null): array { $sql = 'SELECT * FROM `_feed` WHERE category=?'; if ($muted) { $sql .= ' AND ttl < 0'; diff --git a/app/Models/Search.php b/app/Models/Search.php index 14d77cb6f..f5b061512 100644 --- a/app/Models/Search.php +++ b/app/Models/Search.php @@ -234,11 +234,11 @@ class FreshRSS_Search { } /** - * @param array $anArray + * @param array|null $anArray * @return array */ - private static function removeEmptyValues($anArray): array { - return empty($anArray) ? [] : array_filter($anArray, function($value) { return $value !== ''; }); + private static function removeEmptyValues(?array $anArray): array { + return empty($anArray) ? [] : array_filter($anArray, static function(string $value) { return $value !== ''; }); } /** diff --git a/app/Models/Share.php b/app/Models/Share.php index 7bd6de9cf..b01d285f3 100644 --- a/app/Models/Share.php +++ b/app/Models/Share.php @@ -49,7 +49,7 @@ class FreshRSS_Share { self::register($share_options); } - uasort(self::$list_sharing, function ($a, $b) { + uasort(self::$list_sharing, static function (FreshRSS_Share $a, FreshRSS_Share $b) { return strcasecmp($a->name(), $b->name()); }); } @@ -303,7 +303,7 @@ class FreshRSS_Share { * @param array $transform an array containing a list of functions to apply. * @return string the transformed data. */ - private static function transform(string $data, $transform): string { + private static function transform(string $data, array $transform): string { if (!is_array($transform) || empty($transform)) { return $data; } diff --git a/app/Models/StatsDAO.php b/app/Models/StatsDAO.php index 30d7aa2ef..a0a4ec498 100644 --- a/app/Models/StatsDAO.php +++ b/app/Models/StatsDAO.php @@ -13,7 +13,7 @@ class FreshRSS_StatsDAO extends Minz_ModelPdo { * * @return array{'main_stream':array{'total':int,'count_unreads':int,'count_reads':int,'count_favorites':int},'all_feeds':array{'total':int,'count_unreads':int,'count_reads':int,'count_favorites':int}} */ - public function calculateEntryRepartition() { + public function calculateEntryRepartition(): array { return array( 'main_stream' => $this->calculateEntryRepartitionPerFeed(null, true), 'all_feeds' => $this->calculateEntryRepartitionPerFeed(null, false), @@ -57,7 +57,7 @@ SQL; * Calculates entry count per day on a 30 days period. * @return array */ - public function calculateEntryCount() { + public function calculateEntryCount(): array { $count = $this->initEntryCountArray(); $midnight = mktime(0, 0, 0); $oldest = $midnight - (self::ENTRY_COUNT_PERIOD * 86400); @@ -87,7 +87,7 @@ SQL; * Initialize an array for the entry count. * @return array */ - protected function initEntryCountArray() { + protected function initEntryCountArray(): array { return $this->initStatsArray(-self::ENTRY_COUNT_PERIOD, -1); } @@ -348,8 +348,8 @@ SQL; * @param array $data * @return array */ - private function convertToTranslatedJson(array $data = array()) { - $translated = array_map(function($a) { + private function convertToTranslatedJson(array $data = array()): array { + $translated = array_map(static function (string $a) { return _t('gen.date.' . $a); }, $data); diff --git a/app/Models/StatsDAOPGSQL.php b/app/Models/StatsDAOPGSQL.php index 9548027ce..52a99d2f4 100644 --- a/app/Models/StatsDAOPGSQL.php +++ b/app/Models/StatsDAOPGSQL.php @@ -5,7 +5,7 @@ class FreshRSS_StatsDAOPGSQL extends FreshRSS_StatsDAO { /** * Calculates the number of article per hour of the day per feed * - * @param integer $feed id + * @param int $feed id * @return array */ public function calculateEntryRepartitionPerFeedPerHour(?int $feed = null): array { @@ -48,6 +48,9 @@ ORDER BY period ASC SQL; $stm = $this->pdo->query($sql); + if ($stm === false) { + return []; + } $res = $stm->fetchAll(PDO::FETCH_NAMED); switch ($period) { diff --git a/app/Models/StatsDAOSQLite.php b/app/Models/StatsDAOSQLite.php index 632fa17e2..9f292aae6 100644 --- a/app/Models/StatsDAOSQLite.php +++ b/app/Models/StatsDAOSQLite.php @@ -25,6 +25,9 @@ ORDER BY period ASC SQL; $stm = $this->pdo->query($sql); + if ($stm === false) { + return []; + } $res = $stm->fetchAll(PDO::FETCH_NAMED); switch ($period) { diff --git a/app/Models/Tag.php b/app/Models/Tag.php index d88f0c1c2..4ab28a286 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -97,7 +97,7 @@ class FreshRSS_Tag extends Minz_Model { } /** - * @param string|int$value + * @param string|int $value */ public function _nbUnread($value): void { $this->nbUnread = (int)$value; diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php index c27a69f11..0f491e706 100644 --- a/app/Models/TagDAO.php +++ b/app/Models/TagDAO.php @@ -245,7 +245,7 @@ SQL; } /** @return array */ - public function listTagsNewestItemUsec(?int $id_tag = null) { + public function listTagsNewestItemUsec(?int $id_tag = null): array { $sql = 'SELECT t.id AS id_tag, MAX(e.id) AS newest_item_us ' . 'FROM `_tag` t ' . 'LEFT OUTER JOIN `_entrytag` et ON et.id_tag = t.id ' @@ -440,7 +440,7 @@ SQL; * @param array>|array $listDAO * @return array */ - private static function daoToTag(array $listDAO) { + private static function daoToTag(array $listDAO): array { $list = array(); if (!is_array($listDAO)) { $listDAO = array($listDAO); diff --git a/app/Models/TagDAOSQLite.php b/app/Models/TagDAOSQLite.php index 910455546..50683cf84 100644 --- a/app/Models/TagDAOSQLite.php +++ b/app/Models/TagDAOSQLite.php @@ -10,7 +10,7 @@ class FreshRSS_TagDAOSQLite extends FreshRSS_TagDAO { 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) { + if (is_string($showCreate) && stripos($showCreate, 'tag') === false) { return $this->createTagTable(); //v1.12.0 } } diff --git a/app/Models/UserQuery.php b/app/Models/UserQuery.php index 278074362..f0d809378 100644 --- a/app/Models/UserQuery.php +++ b/app/Models/UserQuery.php @@ -34,7 +34,7 @@ class FreshRSS_UserQuery { private $tag_dao; /** - * @param array $query + * @param array $query */ public function __construct(array $query, FreshRSS_FeedDAO $feed_dao = null, FreshRSS_CategoryDAO $category_dao = null, FreshRSS_TagDAO $tag_dao = null) { $this->category_dao = $category_dao; diff --git a/app/Models/View.php b/app/Models/View.php index e908bdfad..87302a4e1 100644 --- a/app/Models/View.php +++ b/app/Models/View.php @@ -57,7 +57,7 @@ class FreshRSS_View extends Minz_View { public $show_email_field; /** @var string */ public $username; - /** @var array */ + /** @var array */ public $users; // Updates @@ -73,7 +73,7 @@ class FreshRSS_View extends Minz_View { public $status_database; // Archiving - /** @var int|false */ + /** @var int */ public $nb_total; /** @var int */ public $size_total; diff --git a/app/Services/ExportService.php b/app/Services/ExportService.php index fd5d48f72..10d5ca2cc 100644 --- a/app/Services/ExportService.php +++ b/app/Services/ExportService.php @@ -87,8 +87,8 @@ class FreshRSS_Export_Service { /** * Generate the entries file content for the given feed. - * @param integer $feed_id - * @param integer $max_number_entries + * @param int $feed_id + * @param int $max_number_entries * @return array{0:string,1:string}|null First item is the filename, second item is the content. * It also can return null if the feed doesn’t exist. */ diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php index 6f6ca13ac..3707e4c5e 100644 --- a/app/Services/ImportService.php +++ b/app/Services/ImportService.php @@ -15,10 +15,8 @@ class FreshRSS_Import_Service { /** * Initialize the service for the given user. - * - * @param string $username */ - public function __construct($username = null) { + public function __construct(?string $username = null) { $this->catDAO = FreshRSS_Factory::createCategoryDao($username); $this->feedDAO = FreshRSS_Factory::createFeedDao($username); } @@ -33,9 +31,9 @@ class FreshRSS_Import_Service { * * @param string $opml_file the OPML file content. * @param FreshRSS_Category|null $forced_category force the feeds to be associated to this category. - * @param boolean $dry_run true to not create categories and feeds in database. + * @param bool $dry_run true to not create categories and feeds in database. */ - public function importOpml(string $opml_file, $forced_category = null, $dry_run = false) { + public function importOpml(string $opml_file, ?FreshRSS_Category $forced_category = null, bool $dry_run = false): void { @set_time_limit(300); $this->lastStatus = true; $opml_array = array(); @@ -132,20 +130,17 @@ class FreshRSS_Import_Service { } } } - - return; } /** * Create a feed from a feed element (i.e. OPML outline). * - * @param array $feed_elt An OPML element (must be a feed element). + * @param array $feed_elt An OPML element (must be a feed element). * @param FreshRSS_Category $category The category to associate to the feed. - * @param boolean $dry_run true to not create the feed in database. - * + * @param bool $dry_run true to not create the feed in database. * @return FreshRSS_Feed|null The created feed, or null if it failed. */ - private function createFeed($feed_elt, $category, $dry_run) { + private function createFeed(array $feed_elt, FreshRSS_Category $category, bool $dry_run): ?FreshRSS_Feed { $url = Minz_Helper::htmlspecialchars_utf8($feed_elt['xmlUrl']); $name = $feed_elt['text'] ?? $feed_elt['title'] ?? ''; $name = Minz_Helper::htmlspecialchars_utf8($name); @@ -256,12 +251,11 @@ class FreshRSS_Import_Service { /** * Create and return a category. * - * @param array $category_element An OPML element (must be a category element). - * @param boolean $dry_run true to not create the category in database. - * + * @param array $category_element An OPML element (must be a category element). + * @param bool $dry_run true to not create the category in database. * @return FreshRSS_Category|null The created category, or null if it failed. */ - private function createCategory($category_element, $dry_run) { + private function createCategory(array $category_element, bool $dry_run): ?FreshRSS_Category { $name = $category_element['text'] ?? $category_element['title'] ?? ''; $name = Minz_Helper::htmlspecialchars_utf8($name); $category = new FreshRSS_Category($name); @@ -295,14 +289,13 @@ class FreshRSS_Import_Service { * This method is applied to a list of outlines. It merges the different * list of feeds from several outlines into one array. * - * @param array $outlines + * @param array $outlines * The outlines from which to extract the outlines. * @param string $parent_category_name * The name of the parent category of the current outlines. - * - * @return array[] + * @return array{0:array,1:array} */ - private function loadFromOutlines($outlines, $parent_category_name) { + private function loadFromOutlines(array $outlines, string $parent_category_name): array { $categories_elements = []; $categories_to_feeds = []; @@ -342,14 +335,14 @@ class FreshRSS_Import_Service { * exists), it will add the outline to an array accessible by its category * name. * - * @param array $outline + * @param array $outline * The outline from which to extract the categories and feeds outlines. * @param string $parent_category_name * The name of the parent category of the current outline. * - * @return array[] + * @return array{0:array,1:array} */ - private function loadFromOutline($outline, $parent_category_name) { + private function loadFromOutline($outline, $parent_category_name): array { $categories_elements = []; $categories_to_feeds = []; @@ -396,7 +389,7 @@ class FreshRSS_Import_Service { return [$categories_elements, $categories_to_feeds]; } - private static function log($message) { + private static function log(string $message): void { if (FreshRSS_Context::$isCli) { fwrite(STDERR, "FreshRSS error during OPML import: {$message}\n"); } else { diff --git a/app/Utils/feverUtil.php b/app/Utils/feverUtil.php index 0e4b712ce..4de321732 100644 --- a/app/Utils/feverUtil.php +++ b/app/Utils/feverUtil.php @@ -57,7 +57,7 @@ class FreshRSS_fever_Util { * * @return bool true if the deletion succeeded, else false. */ - public static function deleteKey(string $username) { + public static function deleteKey(string $username): bool { $userConfig = get_user_configuration($username); if ($userConfig === null) { return false; diff --git a/app/actualize_script.php b/app/actualize_script.php index 4a38c13f7..160911f53 100755 --- a/app/actualize_script.php +++ b/app/actualize_script.php @@ -54,7 +54,7 @@ if (($handle = @fopen($mutexFile, 'x')) === false) { } fclose($handle); -register_shutdown_function(function () use ($mutexFile) { +register_shutdown_function(static function () use ($mutexFile) { unlink($mutexFile); }); // @@ -63,7 +63,7 @@ notice('FreshRSS starting feeds actualization at ' . $begin_date->format('c')); // make sure the PHP setup of the CLI environment is compatible with FreshRSS as well echo 'Failed requirements!', "\n"; -performRequirementCheck(FreshRSS_Context::$system_conf->db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); ob_clean(); echo 'Results: ', "\n"; //Buffered @@ -100,7 +100,7 @@ foreach ($users as $user) { // NB: Extensions and hooks are reinitialised there $app->init(); - Minz_ExtensionManager::addHook('feed_before_actualize', function ($feed) use ($mutexFile) { + Minz_ExtensionManager::addHook('feed_before_actualize', static function (FreshRSS_Feed $feed) use ($mutexFile) { touch($mutexFile); return $feed; }); diff --git a/app/install.php b/app/install.php index b43aa81bb..599fd9863 100644 --- a/app/install.php +++ b/app/install.php @@ -18,7 +18,11 @@ if (STEP === 2 && isset($_POST['type'])) { Minz_Session::_param('bd_type', $_POST['type']); } -function param($key, $default = false) { +/** + * @param mixed $default + * @return mixed + */ +function param(string $key, $default = false) { if (isset($_POST[$key])) { return $_POST[$key]; } else { @@ -27,7 +31,7 @@ function param($key, $default = false) { } // gestion internationalisation -function initTranslate() { +function initTranslate(): void { Minz_Translate::init(); $available_languages = Minz_Translate::availableLanguages(); @@ -42,14 +46,14 @@ function initTranslate() { Minz_Translate::reset(Minz_Session::param('language')); } -function get_best_language() { +function get_best_language(): string { $accept = empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? '' : $_SERVER['HTTP_ACCEPT_LANGUAGE']; return strtolower(substr($accept, 0, 2)); } /*** SAUVEGARDES ***/ -function saveLanguage() { +function saveLanguage(): bool { if (!empty($_POST)) { if (!isset($_POST['language'])) { return false; @@ -60,9 +64,10 @@ function saveLanguage() { header('Location: index.php?step=1'); } + return true; } -function saveStep1() { +function saveStep1(): void { if (isset($_POST['freshrss-keep-install']) && $_POST['freshrss-keep-install'] === '1') { // We want to keep our previous installation of FreshRSS @@ -79,12 +84,12 @@ function saveStep1() { 'auth_type' => FreshRSS_Context::$system_conf->auth_type, 'default_user' => Minz_User::name(), 'passwordHash' => FreshRSS_Context::$user_conf->passwordHash, - 'bd_type' => FreshRSS_Context::$system_conf->db['type'], - 'bd_host' => FreshRSS_Context::$system_conf->db['host'], - 'bd_user' => FreshRSS_Context::$system_conf->db['user'], - 'bd_password' => FreshRSS_Context::$system_conf->db['password'], - 'bd_base' => FreshRSS_Context::$system_conf->db['base'], - 'bd_prefix' => FreshRSS_Context::$system_conf->db['prefix'], + 'bd_type' => FreshRSS_Context::$system_conf->db['type'] ?? '', + 'bd_host' => FreshRSS_Context::$system_conf->db['host'] ?? '', + 'bd_user' => FreshRSS_Context::$system_conf->db['user'] ?? '', + 'bd_password' => FreshRSS_Context::$system_conf->db['password'] ?? '', + 'bd_base' => FreshRSS_Context::$system_conf->db['base'] ?? '', + 'bd_prefix' => FreshRSS_Context::$system_conf->db['prefix'] ?? '', 'bd_error' => false, ]); @@ -92,7 +97,7 @@ function saveStep1() { } } -function saveStep2() { +function saveStep2(): void { if (!empty($_POST)) { if (Minz_Session::param('bd_type') === 'sqlite') { Minz_Session::_params([ @@ -190,9 +195,9 @@ function saveStep2() { invalidateHttpCache(); } -function saveStep3() { +function saveStep3(): bool { if (!empty($_POST)) { - $system_default_config = Minz_Configuration::get('default_system'); + $system_default_config = FreshRSS_SystemConfiguration::get('default_system'); Minz_Session::_params([ 'title' => $system_default_config->title, 'auth_type' => param('auth_type', 'form'), @@ -242,10 +247,11 @@ function saveStep3() { header('Location: index.php?step=4'); } + return true; } /*** VÉRIFICATIONS ***/ -function checkStep() { +function checkStep(): void { $s0 = checkStep0(); $s1 = checkRequirements(); $s2 = checkStep2(); @@ -262,7 +268,8 @@ function checkStep() { Minz_Session::_param('actualize_feeds', true); } -function checkStep0() { +/** @return array */ +function checkStep0(): array { $languages = Minz_Translate::availableLanguages(); $language = Minz_Session::param('language') != '' && in_array(Minz_Session::param('language'), $languages); $sessionWorking = Minz_Session::param('sessionWorking') === 'ok'; @@ -274,7 +281,7 @@ function checkStep0() { ); } -function freshrss_already_installed() { +function freshrss_already_installed(): bool { $conf_path = join_path(DATA_PATH, 'config.php'); if (!file_exists($conf_path)) { return false; @@ -300,7 +307,8 @@ function freshrss_already_installed() { return true; } -function checkStep2() { +/** @return array */ +function checkStep2(): array { $conf = is_writable(join_path(DATA_PATH, 'config.php')); $bd = Minz_Session::param('bd_type') != ''; @@ -314,7 +322,8 @@ function checkStep2() { ]; } -function checkStep3() { +/** @return array */ +function checkStep3(): array { $conf = Minz_Session::param('default_user') != ''; $form = Minz_Session::param('auth_type') != ''; @@ -335,7 +344,7 @@ function checkStep3() { /*** AFFICHAGE ***/ -function printStep0() { +function printStep0(): void { $actual = Minz_Translate::language(); $languages = Minz_Translate::availableLanguages(); $s0 = checkStep0(); @@ -373,7 +382,8 @@ function printStep0() { $messageParams */ +function printStep1Template(string $key, string $value, array $messageParams = []): void { if ('ok' === $value) { $message = _t("install.check.{$key}.ok", ...$messageParams); ?>

@@ -408,14 +420,10 @@ function printStep1() {

@@ -509,7 +517,7 @@ function printStep2() {
+ isset($_SESSION['bd_host']) ? $_SESSION['bd_host'] : ($system_default_config->db['host'] ?? '') ?>" tabindex="2" />
@@ -544,7 +552,7 @@ function printStep2() {
+ isset($_SESSION['bd_prefix']) ? $_SESSION['bd_prefix'] : ($system_default_config->db['prefix'] ?? '') ?>" tabindex="7" />
@@ -562,11 +570,11 @@ function printStep2() { @@ -628,7 +636,7 @@ function printStep3() {

@@ -639,7 +647,7 @@ function printStep4() {

@@ -676,7 +684,7 @@ case 5: } ?> - array(), ); -echo rtrim(json_encode($articles, $options), " ]}\n\r\t"), "\n"; +echo rtrim(json_encode($articles, $options) ?: '', " ]}\n\r\t"), "\n"; $first = true; if (empty($this->entryIdsTagNames)) { diff --git a/app/views/helpers/export/opml.phtml b/app/views/helpers/export/opml.phtml index 4df36b122..5acdff374 100644 --- a/app/views/helpers/export/opml.phtml +++ b/app/views/helpers/export/opml.phtml @@ -4,7 +4,7 @@ * @param array $feeds * @return array> */ -function feedsToOutlines($feeds, bool $excludeMutedFeeds = false): array { +function feedsToOutlines(array $feeds, bool $excludeMutedFeeds = false): array { $outlines = []; foreach ($feeds as $feed) { if ($feed->mute() && $excludeMutedFeeds) { @@ -98,4 +98,6 @@ if (!empty($this->feeds)) { } $libopml = new \marienfressinaud\LibOpml\LibOpml(true); -echo $libopml->render($opml_array); +$opml = $libopml->render($opml_array); +/** @var string $opml */ +echo $opml; diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index e108f5a34..03ed96a9e 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -72,4 +72,4 @@ echo htmlspecialchars(json_encode(array( 'unread' => rawurlencode(_i('unread')), ), 'extensions' => $extData, -), JSON_UNESCAPED_UNICODE), ENT_NOQUOTES, 'UTF-8'); +), JSON_UNESCAPED_UNICODE) ?: '', ENT_NOQUOTES, 'UTF-8'); diff --git a/app/views/index/logs.phtml b/app/views/index/logs.phtml index 54b7e1c6b..42be022d6 100644 --- a/app/views/index/logs.phtml +++ b/app/views/index/logs.phtml @@ -14,7 +14,7 @@ ?> - logsPaginator->render('logs_pagination.phtml', 0); ?> + logsPaginator->render('logs_pagination.phtml'); ?>

@@ -41,7 +41,7 @@
- logsPaginator->render('logs_pagination.phtml', 0); ?> + logsPaginator->render('logs_pagination.phtml'); ?> diff --git a/app/views/index/normal.phtml b/app/views/index/normal.phtml index 02b336bf7..ede772a78 100644 --- a/app/views/index/normal.phtml +++ b/app/views/index/normal.phtml @@ -40,7 +40,7 @@ $today = @strtotime('today'); // We most likely already have the feed object in cache $this->feed = FreshRSS_CategoryDAO::findFeed($this->categories, $this->entry->feedId()); if ($this->feed == null) { - $this->feed = $this->entry->feed(); + $this->feed = $this->entry->feed() ?: null; if ($this->feed == null) { $this->feed = FreshRSS_Feed::example(); } diff --git a/app/views/stats/idle.phtml b/app/views/stats/idle.phtml index fcab1e8e3..d94256860 100644 --- a/app/views/stats/idle.phtml +++ b/app/views/stats/idle.phtml @@ -45,7 +45,7 @@
  • show_favicons): ?>✇ - + ()
  • diff --git a/cli/_cli.php b/cli/_cli.php index 8a6b13007..710e26605 100644 --- a/cli/_cli.php +++ b/cli/_cli.php @@ -77,10 +77,10 @@ function performRequirementCheck(string $databaseType): void { * @return array */ function getLongOptions(array $options, string $regex): array { - $longOptions = array_filter($options, function($a) use ($regex) { + $longOptions = array_filter($options, static function (string $a) use ($regex) { return preg_match($regex, $a); }); - return array_map(function($a) use ($regex) { + return array_map(static function (string $a) use ($regex) { return preg_replace($regex, '', $a); }, $longOptions); } diff --git a/cli/_update-or-create-user.php b/cli/_update-or-create-user.php index 0f6c39517..73b627597 100644 --- a/cli/_update-or-create-user.php +++ b/cli/_update-or-create-user.php @@ -1,7 +1,7 @@ db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); $params = array( 'user:', diff --git a/cli/actualize-user.php b/cli/actualize-user.php index c267da648..b7bc9c2ad 100755 --- a/cli/actualize-user.php +++ b/cli/actualize-user.php @@ -2,7 +2,7 @@ db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); $params = array( 'user:', @@ -10,7 +10,7 @@ $params = array( $options = getopt('', $params); -if (!validateOptions($argv, $params) || empty($options['user'])) { +if (!validateOptions($argv, $params) || empty($options['user']) || !is_string($options['user'])) { fail('Usage: ' . basename(__FILE__) . " --user username"); } diff --git a/cli/db-optimize.php b/cli/db-optimize.php index 757b94ef6..ba14d12ea 100755 --- a/cli/db-optimize.php +++ b/cli/db-optimize.php @@ -2,7 +2,7 @@ db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); $params = array( 'user:', @@ -10,7 +10,7 @@ $params = array( $options = getopt('', $params); -if (!validateOptions($argv, $params) || empty($options['user'])) { +if (!validateOptions($argv, $params) || empty($options['user']) || !is_string($options['user'])) { fail('Usage: ' . basename(__FILE__) . " --user username"); } diff --git a/cli/delete-user.php b/cli/delete-user.php index 86424e9f7..fbbb2eebb 100755 --- a/cli/delete-user.php +++ b/cli/delete-user.php @@ -2,7 +2,7 @@ db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); $params = array( 'user:', @@ -10,7 +10,7 @@ $params = array( $options = getopt('', $params); -if (!validateOptions($argv, $params) || empty($options['user'])) { +if (!validateOptions($argv, $params) || empty($options['user']) || !is_string($options['user'])) { fail('Usage: ' . basename(__FILE__) . " --user username"); } $username = $options['user']; diff --git a/cli/export-opml-for-user.php b/cli/export-opml-for-user.php index 2f728742a..755cbe035 100755 --- a/cli/export-opml-for-user.php +++ b/cli/export-opml-for-user.php @@ -2,7 +2,7 @@ db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); $params = array( 'user:', @@ -10,7 +10,7 @@ $params = array( $options = getopt('', $params); -if (!validateOptions($argv, $params) || empty($options['user'])) { +if (!validateOptions($argv, $params) || empty($options['user']) || !is_string($options['user'])) { fail('Usage: ' . basename(__FILE__) . " --user username > /path/to/file.opml.xml"); } diff --git a/cli/export-sqlite-for-user.php b/cli/export-sqlite-for-user.php index 78c21ce1e..b4265d28a 100755 --- a/cli/export-sqlite-for-user.php +++ b/cli/export-sqlite-for-user.php @@ -2,7 +2,7 @@ db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); $params = [ 'user:', @@ -11,7 +11,7 @@ $params = [ $options = getopt('', $params); -if (!validateOptions($argv, $params) || empty($options['user']) || empty($options['filename'])) { +if (!validateOptions($argv, $params) || empty($options['user']) || empty($options['filename']) || !is_string($options['user']) || !is_string($options['filename'])) { fail('Usage: ' . basename(__FILE__) . ' --user username --filename /path/to/db.sqlite'); } diff --git a/cli/export-zip-for-user.php b/cli/export-zip-for-user.php index a650b10f4..90e4b87e1 100755 --- a/cli/export-zip-for-user.php +++ b/cli/export-zip-for-user.php @@ -2,7 +2,7 @@ db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); $params = array( 'user:', @@ -11,7 +11,7 @@ $params = array( $options = getopt('', $params); -if (!validateOptions($argv, $params) || empty($options['user'])) { +if (!validateOptions($argv, $params) || empty($options['user']) || !is_string($options['user'])) { fail('Usage: ' . basename(__FILE__) . " --user username ( --max-feed-entries 100 ) > /path/to/file.zip"); } diff --git a/cli/i18n/I18nData.php b/cli/i18n/I18nData.php index b3bb6e34f..62ffd7ce1 100644 --- a/cli/i18n/I18nData.php +++ b/cli/i18n/I18nData.php @@ -127,7 +127,7 @@ class I18nData { * the parent key is 'a.b.c.d'. */ private function getParentKey(string $key): string { - return substr($key, 0, strrpos($key, '.')); + return substr($key, 0, strrpos($key, '.') ?: null); } /** @@ -183,7 +183,7 @@ class I18nData { } $keys = array_keys($this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)]); - $children = array_values(array_filter($keys, function ($element) use ($key) { + $children = array_values(array_filter($keys, static function (string $element) use ($key) { if ($element === $key) { return false; } diff --git a/cli/import-for-user.php b/cli/import-for-user.php index 2bfc1b842..405843133 100755 --- a/cli/import-for-user.php +++ b/cli/import-for-user.php @@ -2,7 +2,7 @@ db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); $params = array( 'user:', @@ -11,7 +11,7 @@ $params = array( $options = getopt('', $params); -if (!validateOptions($argv, $params) || empty($options['user']) || empty($options['filename'])) { +if (!validateOptions($argv, $params) || empty($options['user']) || empty($options['filename']) || !is_string($options['user']) || !is_string($options['filename'])) { fail('Usage: ' . basename(__FILE__) . " --user username --filename /path/to/file.ext"); } diff --git a/cli/import-sqlite-for-user.php b/cli/import-sqlite-for-user.php index 544a82a72..3d1fcc7bf 100755 --- a/cli/import-sqlite-for-user.php +++ b/cli/import-sqlite-for-user.php @@ -2,7 +2,7 @@ db['type']); +performRequirementCheck(FreshRSS_Context::$system_conf->db['type'] ?? ''); $params = [ 'user:', @@ -12,7 +12,7 @@ $params = [ $options = getopt('', $params); -if (!validateOptions($argv, $params) || empty($options['user']) || empty($options['filename'])) { +if (!validateOptions($argv, $params) || empty($options['user']) || empty($options['filename']) || !is_string($options['user']) || !is_string($options['filename'])) { fail('Usage: ' . basename(__FILE__) . ' --user username --force-overwrite --filename /path/to/db.sqlite'); } diff --git a/cli/user-info.php b/cli/user-info.php index f338cbc17..8fc8f20df 100755 --- a/cli/user-info.php +++ b/cli/user-info.php @@ -71,12 +71,12 @@ foreach ($users as $username) { 'enabled' => FreshRSS_Context::$user_conf->enabled ? '*' : '', 'last_user_activity' => FreshRSS_UserDAO::mtime($username), 'database_size' => $databaseDAO->size(), - 'categories' => (int) $catDAO->count(), - 'feeds' => (int) count($feedDAO->listFeedsIds()), - 'reads' => (int) $nbEntries['read'], - 'unreads' => (int) $nbEntries['unread'], - 'favourites' => (int) $nbFavorites['all'], - 'tags' => (int) $tagDAO->count(), + 'categories' => $catDAO->count(), + 'feeds' => count($feedDAO->listFeedsIds()), + 'reads' => (int)$nbEntries['read'], + 'unreads' => (int)$nbEntries['unread'], + 'favourites' => (int)$nbFavorites['all'], + 'tags' => (int)$tagDAO->count(), 'lang' => FreshRSS_Context::$user_conf->language, 'mail_login' => FreshRSS_Context::$user_conf->mail_login, ); diff --git a/composer.json b/composer.json index f6d2555f5..c0761fd79 100644 --- a/composer.json +++ b/composer.json @@ -49,7 +49,8 @@ "ext-phar": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "phpstan/phpstan": "~1.9.17", + "phpstan/phpstan": "~1.10.13", + "phpstan/phpstan-phpunit": "^1.3", "phpunit/phpunit": "^9", "squizlabs/php_codesniffer": "^3.7" }, @@ -59,7 +60,7 @@ "phpcs": "phpcs . -s", "phpcbf": "phpcbf . -p -s", "phpstan": "phpstan analyse --memory-limit 512M .", - "phpstan-next": "phpstan analyse --level 6 --memory-limit 512M $(find . -type d -name 'vendor' -prune -o -name '*.php' -o -name '*.phtml' | grep -Fxvf ./tests/phpstan-next.txt | sort | paste -s)", + "phpstan-next": "phpstan analyse --level 7 --memory-limit 512M $(find . -type d -name 'vendor' -prune -o -name '*.php' -o -name '*.phtml' | grep -Fxvf ./tests/phpstan-next.txt | sort | paste -s)", "phpunit": "phpunit --bootstrap ./tests/bootstrap.php --verbose ./tests", "translations": "cli/manipulate.translation.php -a format", "test": [ @@ -74,5 +75,10 @@ "@translations", "@phpcbf" ] + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": false + } } } diff --git a/composer.lock b/composer.lock index 74a7155d8..33ad6dfaa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,35 +4,35 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4dcbcd3ba9c1dbed63612651a725dab8", + "content-hash": "194c10da954d3f120fef1e0b21c34546", "packages": [], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -59,7 +59,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -75,20 +75,20 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { @@ -126,7 +126,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { @@ -134,20 +134,20 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { "name": "nikic/php-parser", - "version": "v4.15.2", + "version": "v4.15.4", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc" + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc", - "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", "shasum": "" }, "require": { @@ -188,9 +188,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" }, - "time": "2022-11-12T15:38:23+00:00" + "time": "2023-03-05T19:49:14+00:00" }, { "name": "phar-io/manifest", @@ -305,16 +305,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.9.17", + "version": "1.10.13", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "204e459e7822f2c586463029f5ecec31bb45a1f2" + "reference": "f07bf8c6980b81bf9e49d44bd0caf2e737614a70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/204e459e7822f2c586463029f5ecec31bb45a1f2", - "reference": "204e459e7822f2c586463029f5ecec31bb45a1f2", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f07bf8c6980b81bf9e49d44bd0caf2e737614a70", + "reference": "f07bf8c6980b81bf9e49d44bd0caf2e737614a70", "shasum": "" }, "require": { @@ -343,8 +343,11 @@ "static analysis" ], "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.9.17" + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, "funding": [ { @@ -360,27 +363,79 @@ "type": "tidelift" } ], - "time": "2023-02-08T12:25:00+00:00" + "time": "2023-04-12T19:29:52+00:00" + }, + { + "name": "phpstan/phpstan-phpunit", + "version": "1.3.11", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-phpunit.git", + "reference": "9e1b9de6d260461f6e99b6a8f2dbb0bbb98b579c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/9e1b9de6d260461f6e99b6a8f2dbb0bbb98b579c", + "reference": "9e1b9de6d260461f6e99b6a8f2dbb0bbb98b579c", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.10" + }, + "conflict": { + "phpunit/phpunit": "<7.0" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPUnit extensions and rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-phpunit/issues", + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.11" + }, + "time": "2023-03-25T19:42:13+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.23", + "version": "9.2.26", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c" + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", - "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", + "nikic/php-parser": "^4.15", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -395,8 +450,8 @@ "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { @@ -429,7 +484,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" }, "funding": [ { @@ -437,7 +492,7 @@ "type": "github" } ], - "time": "2022-12-28T12:41:10+00:00" + "time": "2023-03-06T12:58:08+00:00" }, { "name": "phpunit/php-file-iterator", @@ -682,20 +737,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.27", + "version": "9.6.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38" + "reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a2bc7ffdca99f92d959b3f2270529334030bba38", - "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c993f0d3b0489ffc42ee2fe0bd645af1538a63b2", + "reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -724,8 +779,8 @@ "sebastian/version": "^3.0.2" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -733,7 +788,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -764,7 +819,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.27" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.7" }, "funding": [ { @@ -780,7 +836,7 @@ "type": "tidelift" } ], - "time": "2022-12-09T07:31:23+00:00" + "time": "2023-04-14T08:58:40+00:00" }, { "name": "sebastian/cli-parser", @@ -1148,16 +1204,16 @@ }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -1199,7 +1255,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -1207,7 +1263,7 @@ "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", @@ -1521,16 +1577,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -1569,10 +1625,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -1580,7 +1636,7 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -1639,16 +1695,16 @@ }, { "name": "sebastian/type", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -1683,7 +1739,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -1691,7 +1747,7 @@ "type": "github" } ], - "time": "2022-09-12T14:47:03+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -1748,16 +1804,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.7.1", + "version": "3.7.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", "shasum": "" }, "require": { @@ -1793,14 +1849,15 @@ "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ "phpcs", - "standards" + "standards", + "static analysis" ], "support": { "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2022-06-18T07:21:10+00:00" + "time": "2023-02-22T23:07:41+00:00" }, { "name": "theseer/tokenizer", @@ -1867,9 +1924,11 @@ "ext-gmp": "*", "ext-intl": "*", "ext-json": "*", + "ext-libxml": "*", "ext-mbstring": "*", "ext-openssl": "*", "ext-pcre": "*", + "ext-pdo": "*", "ext-pdo_sqlite": "*", "ext-session": "*", "ext-simplexml": "*", @@ -1885,5 +1944,5 @@ "ext-tokenizer": "*", "ext-xmlwriter": "*" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index 4259c4052..d641d8994 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -3,7 +3,8 @@ /** * Manage configuration for the application. * @property-read string $base_url - * @property array> $db + * @property array{'type'?:string,'host'?:string,'user'?:string,'password'?:string,'base'?:string,'prefix'?:string, + * 'connection_uri_params'?:string,'pdo_options'?:array} $db * @property-read string $disable_update * @property-read string $environment * @property array $extensions_enabled @@ -24,9 +25,10 @@ class Minz_Configuration { * @param string $namespace the name of the current configuration * @param string $config_filename the filename of the configuration * @param string $default_filename a filename containing default values for the configuration - * @param object $configuration_setter an optional helper to set values in configuration + * @param Minz_ConfigurationSetterInterface $configuration_setter an optional helper to set values in configuration */ - public static function register(string $namespace, string $config_filename, string $default_filename = null, object $configuration_setter = null): void { + public static function register(string $namespace, string $config_filename, string $default_filename = null, + Minz_ConfigurationSetterInterface $configuration_setter = null): void { self::$config_list[$namespace] = new static( $namespace, $config_filename, $default_filename, $configuration_setter ); @@ -92,9 +94,9 @@ class Minz_Configuration { /** * An object which help to set good values in configuration. - * @var object|null + * @var Minz_ConfigurationSetterInterface|null */ - private $configuration_setter = null; + private $configuration_setter; /** * Create a new Minz_Configuration object. @@ -102,9 +104,10 @@ class Minz_Configuration { * @param string $namespace the name of the current configuration. * @param string $config_filename the file containing configuration values. * @param string $default_filename the file containing default values, null by default. - * @param object $configuration_setter an optional helper to set values in configuration + * @param Minz_ConfigurationSetterInterface $configuration_setter an optional helper to set values in configuration */ - private final function __construct(string $namespace, string $config_filename, string $default_filename = null, object $configuration_setter = null) { + private final function __construct(string $namespace, string $config_filename, string $default_filename = null, + Minz_ConfigurationSetterInterface $configuration_setter = null) { $this->namespace = $namespace; $this->config_filename = $config_filename; $this->default_filename = $default_filename; @@ -127,16 +130,15 @@ class Minz_Configuration { /** * Set a configuration setter for the current configuration. - * @param object|null $configuration_setter the setter to call when modifying data. It - * must implement an handle($key, $value) method. + * @param Minz_ConfigurationSetterInterface|null $configuration_setter the setter to call when modifying data. */ - public function _configurationSetter(?object $configuration_setter): void { + public function _configurationSetter(?Minz_ConfigurationSetterInterface $configuration_setter): void { if (is_callable(array($configuration_setter, 'handle'))) { $this->configuration_setter = $configuration_setter; } } - public function configurationSetter(): object { + public function configurationSetter(): ?Minz_ConfigurationSetterInterface { return $this->configuration_setter; } @@ -181,11 +183,11 @@ class Minz_Configuration { * @param mixed $value the value to set. If null, the key is removed from the configuration. */ public function _param(string $key, $value = null): void { - if (!is_null($this->configuration_setter) && $this->configuration_setter->support($key)) { + if ($this->configuration_setter !== null && $this->configuration_setter->support($key)) { $this->configuration_setter->handle($this->data, $key, $value); } elseif (isset($this->data[$key]) && is_null($value)) { unset($this->data[$key]); - } elseif (!is_null($value)) { + } elseif ($value !== null) { $this->data[$key] = $value; } } diff --git a/lib/Minz/ConfigurationSetterInterface.php b/lib/Minz/ConfigurationSetterInterface.php new file mode 100644 index 000000000..ac8c154ba --- /dev/null +++ b/lib/Minz/ConfigurationSetterInterface.php @@ -0,0 +1,19 @@ + $data an array containing the list of all configuration data. + * @param string $key the key to update. + * @param mixed $value the value to set. + */ + public function handle(&$data, string $key, $value): void; +} diff --git a/lib/Minz/Dispatcher.php b/lib/Minz/Dispatcher.php index 128207025..abc7efe21 100644 --- a/lib/Minz/Dispatcher.php +++ b/lib/Minz/Dispatcher.php @@ -87,19 +87,21 @@ class Minz_Dispatcher { $controller_name = 'FreshRSS_' . $base_name . '_Controller'; } - if (!class_exists ($controller_name)) { + if (!class_exists($controller_name)) { throw new Minz_ControllerNotExistException ( Minz_Exception::ERROR ); } - $this->controller = new $controller_name (); + $controller = new $controller_name(); - if (! ($this->controller instanceof Minz_ActionController)) { + if (!($controller instanceof Minz_ActionController)) { throw new Minz_ControllerNotActionControllerException ( $controller_name, Minz_Exception::ERROR ); } + + $this->controller = $controller; } /** @@ -108,20 +110,15 @@ class Minz_Dispatcher { * @throws Minz_ActionException if the action cannot be executed on the controller */ private function launchAction(string $action_name): void { - if (!is_callable (array ( - $this->controller, - $action_name - ))) { + $call = [$this->controller, $action_name]; + if (!is_callable($call)) { throw new Minz_ActionException ( - get_class ($this->controller), + get_class($this->controller), $action_name, Minz_Exception::ERROR ); } - call_user_func (array ( - $this->controller, - $action_name - )); + call_user_func($call); } /** @@ -140,9 +137,9 @@ class Minz_Dispatcher { * Return if a controller is registered. * * @param string $base_name the base name of the controller. - * @return boolean true if the controller has been registered, false else. + * @return bool true if the controller has been registered, false else. */ - public static function isRegistered(string $base_name) { + public static function isRegistered(string $base_name): bool { return isset(self::$registrations[$base_name]); } diff --git a/lib/Minz/Error.php b/lib/Minz/Error.php index e23499a10..15be7b8b4 100644 --- a/lib/Minz/Error.php +++ b/lib/Minz/Error.php @@ -52,7 +52,7 @@ class Minz_Error { * @param array|string $logs logs sorted by category (error, warning, notice) * @return array list of matching logs, without the category, according to environment preferences (production / development) */ - private static function processLogs($logs) { + private static function processLogs($logs): array { $conf = Minz_Configuration::get('system'); $env = $conf->environment; $logs_ok = array (); diff --git a/lib/Minz/Extension.php b/lib/Minz/Extension.php index e95fe7160..8fe8c38b4 100644 --- a/lib/Minz/Extension.php +++ b/lib/Minz/Extension.php @@ -217,7 +217,7 @@ abstract class Minz_Extension { } /** @param 'system'|'user' $type */ - private function isConfigurationEnabled($type): bool { + private function isConfigurationEnabled(string $type): bool { if (!class_exists('FreshRSS_Context', false)) { return false; } @@ -229,7 +229,7 @@ abstract class Minz_Extension { } /** @param 'system'|'user' $type */ - private function isExtensionConfigured($type): bool { + private function isExtensionConfigured(string $type): bool { switch ($type) { case 'system': $conf = FreshRSS_Context::$user_conf; @@ -248,7 +248,7 @@ abstract class Minz_Extension { } /** - * @param 'system'|'user' $type + * @phpstan-param 'system'|'user' $type * @return array */ private function getConfiguration(string $type): array { @@ -338,7 +338,7 @@ abstract class Minz_Extension { $this->user_configuration = $configuration; } - /** @param 'system'|'user' $type */ + /** @phpstan-param 'system'|'user' $type */ private function removeConfiguration(string $type): void { if (!$this->isConfigurationEnabled($type)) { return; diff --git a/lib/Minz/ExtensionManager.php b/lib/Minz/ExtensionManager.php index 9c0eaf001..0e1c72885 100644 --- a/lib/Minz/ExtensionManager.php +++ b/lib/Minz/ExtensionManager.php @@ -364,7 +364,7 @@ final class Minz_ExtensionManager { foreach (self::$hook_list[$hook_name]['list'] as $function) { $result = call_user_func($function, $arg); - if (is_null($result)) { + if ($result === null) { break; } diff --git a/lib/Minz/FrontController.php b/lib/Minz/FrontController.php index 4837f89c1..3268b5763 100644 --- a/lib/Minz/FrontController.php +++ b/lib/Minz/FrontController.php @@ -39,11 +39,11 @@ class Minz_FrontController { Minz_Request::init(); $url = Minz_Url::build(); - $url['params'] = array_merge ( - $url['params'], + $url['params'] = array_merge( + empty($url['params']) || !is_array($url['params']) ? [] : $url['params'], $_POST ); - Minz_Request::forward ($url); + Minz_Request::forward($url); } catch (Minz_Exception $e) { Minz_Log::error($e->getMessage()); self::killApp($e->getMessage()); diff --git a/lib/Minz/Mailer.php b/lib/Minz/Mailer.php index ba434ec8f..cf6c64bad 100644 --- a/lib/Minz/Mailer.php +++ b/lib/Minz/Mailer.php @@ -44,7 +44,7 @@ class Minz_Mailer { */ public function __construct () { $this->view = new Minz_View(); - $this->view->_layout(false); + $this->view->_layout(null); $this->view->attributeParams(); $conf = Minz_Configuration::get('system'); @@ -66,10 +66,9 @@ class Minz_Mailer { * * @param string $to The recipient of the email * @param string $subject The subject of the email - * * @return bool true on success, false if a SMTP error happens */ - public function mail($to, $subject) { + public function mail(string $to, string $subject): bool { ob_start(); $this->view->render(); $body = ob_get_contents(); diff --git a/lib/Minz/Migrator.php b/lib/Minz/Migrator.php index 661bc9c5d..ef4bce48f 100644 --- a/lib/Minz/Migrator.php +++ b/lib/Minz/Migrator.php @@ -38,11 +38,11 @@ class Minz_Migrator $applied_migrations = array_filter(explode("\n", $applied_migrations)); $migration_files = scandir($migrations_path); - $migration_files = array_filter($migration_files, function ($filename) { + $migration_files = array_filter($migration_files, static function (string $filename) { $file_extension = pathinfo($filename, PATHINFO_EXTENSION); return $file_extension === 'php'; }); - $migration_versions = array_map(function ($filename) { + $migration_versions = array_map(static function (string $filename) { return basename($filename, '.php'); }, $migration_files); @@ -225,9 +225,8 @@ class Minz_Migrator } /** - * @return boolean Return true if the application is up-to-date, false - * otherwise. If no migrations are registered, it always - * returns true. + * @return bool Return true if the application is up-to-date, false otherwise. + * If no migrations are registered, it always returns true. */ public function upToDate(): bool { // Counting versions is enough since we cannot apply a version which diff --git a/lib/Minz/ModelArray.php b/lib/Minz/ModelArray.php index 0d8b71f91..d2f518344 100644 --- a/lib/Minz/ModelArray.php +++ b/lib/Minz/ModelArray.php @@ -19,7 +19,7 @@ class Minz_ModelArray { * @param string $filename le nom du fichier à ouvrir contenant un tableau * Remarque : $array sera obligatoirement un tableau */ - public function __construct ($filename) { + public function __construct(string $filename) { $this->filename = $filename; } diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php index 0e813ddca..dc3d0a42c 100644 --- a/lib/Minz/ModelPdo.php +++ b/lib/Minz/ModelPdo.php @@ -102,7 +102,7 @@ class Minz_ModelPdo { * @throws Minz_ConfigurationNamespaceException * @throws Minz_PDOConnectionException */ - public function __construct($currentUser = null, $currentPdo = null) { + public function __construct(?string $currentUser = null, ?Minz_Pdo $currentPdo = null) { if ($currentUser === null) { $currentUser = Minz_User::name(); } diff --git a/lib/Minz/Paginator.php b/lib/Minz/Paginator.php index e11dda11c..77bc3e5e0 100644 --- a/lib/Minz/Paginator.php +++ b/lib/Minz/Paginator.php @@ -37,11 +37,11 @@ class Minz_Paginator { * Constructeur * @param array $items les éléments à gérer */ - public function __construct ($items) { - $this->_items ($items); - $this->_nbItems (count ($this->items (true))); - $this->_nbItemsPerPage ($this->nbItemsPerPage); - $this->_currentPage ($this->currentPage); + public function __construct(array $items) { + $this->_items($items); + $this->_nbItems(count($this->items(true))); + $this->_nbItemsPerPage($this->nbItemsPerPage); + $this->_currentPage($this->currentPage); } /** @@ -49,25 +49,25 @@ class Minz_Paginator { * @param string $view nom du fichier de vue situé dans /app/views/helpers/ * @param int $getteur variable de type $_GET[] permettant de retrouver la page */ - public function render ($view, $getteur) { + public function render(string $view, int $getteur = 0): void { $view = APP_PATH . '/views/helpers/' . $view; - if (file_exists ($view)) { - include ($view); + if (file_exists($view)) { + include($view); } } /** * Permet de retrouver la page d'un élément donné * @param Minz_Model $item l'élément à retrouver - * @return float|false la page à laquelle se trouve l’élément, false si non trouvé + * @return int|false la page à laquelle se trouve l’élément, false si non trouvé */ - public function pageByItem ($item) { + public function pageByItem($item) { $i = 0; do { if ($item == $this->items[$i]) { - return ceil(($i + 1) / $this->nbItemsPerPage); + return (int)(ceil(($i + 1) / $this->nbItemsPerPage)); } $i++; } while ($i < $this->nbItems()); @@ -80,7 +80,7 @@ class Minz_Paginator { * @param Minz_Model $item the element to search * @return int|false the position of the element, or false if not found */ - public function positionByItem ($item) { + public function positionByItem($item) { $i = 0; do { @@ -96,9 +96,9 @@ class Minz_Paginator { /** * Permet de récupérer un item par sa position * @param int $pos la position de l'élément - * @return mixed item situé à $pos (dernier item si $pos<0, 1er si $pos>=count($items)) + * @return Minz_Model item situé à $pos (dernier item si $pos<0, 1er si $pos>=count($items)) */ - public function itemByPosition ($pos) { + public function itemByPosition(int $pos): Minz_Model { if ($pos < 0) { $pos = $this->nbItems () - 1; } @@ -116,7 +116,7 @@ class Minz_Paginator { * @param bool $all si à true, retourne tous les éléments sans prendre en compte la pagination * @return array */ - public function items ($all = false) { + public function items(bool $all = false): array { $array = array (); $nbItems = $this->nbItems (); @@ -141,30 +141,28 @@ class Minz_Paginator { return $array; } - public function nbItemsPerPage () { + public function nbItemsPerPage(): int { return $this->nbItemsPerPage; } - public function currentPage () { + public function currentPage(): int { return $this->currentPage; } - public function nbPage () { + public function nbPage(): int { return $this->nbPage; } - public function nbItems () { + public function nbItems(): int { return $this->nbItems; } /** * SETTEURS */ - public function _items ($items) { - if (is_array ($items)) { - $this->items = $items; - } - - $this->_nbPage (); + /** @param array $items */ + public function _items(?array $items): void { + $this->items = $items ?? []; + $this->_nbPage(); } - public function _nbItemsPerPage ($nbItemsPerPage) { + public function _nbItemsPerPage(int $nbItemsPerPage): void { if ($nbItemsPerPage > $this->nbItems ()) { $nbItemsPerPage = $this->nbItems (); } @@ -173,21 +171,21 @@ class Minz_Paginator { } $this->nbItemsPerPage = $nbItemsPerPage; - $this->_nbPage (); + $this->_nbPage(); } - public function _currentPage ($page) { + public function _currentPage(int $page): void { if ($page < 1 || ($page > $this->nbPage && $this->nbPage > 0)) { throw new Minz_CurrentPagePaginationException($page); } $this->currentPage = $page; } - private function _nbPage () { + private function _nbPage(): void { if ($this->nbItemsPerPage > 0) { $this->nbPage = (int)ceil($this->nbItems() / $this->nbItemsPerPage); } } - public function _nbItems ($value) { + public function _nbItems(int $value): void { $this->nbItems = $value; } } diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php index 7957610e2..ca9957eab 100644 --- a/lib/Minz/Request.php +++ b/lib/Minz/Request.php @@ -298,7 +298,7 @@ class Minz_Request { * localhost address. * * @param string $address the address to test, can be an IP or a URL. - * @return boolean true if server is accessible, false otherwise. + * @return bool true if server is accessible, false otherwise. * @todo improve test with a more valid technique (e.g. test with an external server?) */ public static function serverIsPublic(string $address): bool { @@ -360,7 +360,7 @@ class Minz_Request { $requests = Minz_Session::param('requests'); if ($requests) { //Delete abandoned notifications - $requests = array_filter($requests, function ($r) { return isset($r['time']) && $r['time'] > time() - 3600; }); + $requests = array_filter($requests, static function (array $r) { return isset($r['time']) && $r['time'] > time() - 3600; }); $requestId = self::requestId(); if (!empty($requests[$requestId]['notification'])) { diff --git a/lib/Minz/Translate.php b/lib/Minz/Translate.php index e4c1020d5..0d704a85f 100644 --- a/lib/Minz/Translate.php +++ b/lib/Minz/Translate.php @@ -133,8 +133,8 @@ class Minz_Translate { } $list_i18n_files = array_values(array_diff( - scandir($lang_path), - array('..', '.') + scandir($lang_path) ?: [], + ['..', '.'] )); // Each file basename correspond to a top-level i18n key. For each of @@ -199,8 +199,7 @@ class Minz_Translate { // If $translates[$top_level] is null it means we have to load the // corresponding files. - if (!isset(self::$translates[$top_level]) || - is_null(self::$translates[$top_level])) { + if (empty(self::$translates[$top_level])) { $res = self::loadKey($top_level); if (!$res) { return $key; diff --git a/lib/Minz/Url.php b/lib/Minz/Url.php index 1350973c1..f0df93b69 100644 --- a/lib/Minz/Url.php +++ b/lib/Minz/Url.php @@ -60,7 +60,7 @@ class Minz_Url { * @param string $encodage pour indiquer comment encoder les & (& ou & pour html) * @return string uri sous la forme ?key=value&key2=value2 */ - private static function printUri($url, string $encodage): string { + private static function printUri(array $url, string $encodage): string { $uri = ''; $separator = '?'; $anchor = ''; @@ -108,23 +108,15 @@ class Minz_Url { /** * Check that all array elements representing the controller URL are OK - * @param array> $url controller URL as array + * @param array> $url controller URL as array * @return array{'c':string,'a':string,'params':array} Verified controller URL as array */ - public static function checkControllerUrl(array $url) { - $url_checked = $url; - - if (empty($url['c'])) { - $url_checked['c'] = Minz_Request::defaultControllerName(); - } - if (empty($url['a'])) { - $url_checked['a'] = Minz_Request::defaultActionName(); - } - if (empty($url['params'])) { - $url_checked['params'] = []; - } - - return $url_checked; + public static function checkControllerUrl(array $url): array { + return [ + 'c' => empty($url['c']) || !is_string($url['c']) ? Minz_Request::defaultControllerName() : $url['c'], + 'a' => empty($url['a']) || !is_string($url['a']) ? Minz_Request::defaultActionName() : $url['a'], + 'params' => empty($url['params']) || !is_array($url['params']) ? [] : $url['params'], + ]; } /** @param array>|null $url */ @@ -139,7 +131,10 @@ class Minz_Url { } } - /** @return array> */ + /** + * @phpstan-return array{'c'?:string,'a'?:string,'params'?:array} + * @return array> + */ public static function unserialize(string $url = ''): array { try { return json_decode(base64_decode($url), true, JSON_THROW_ON_ERROR) ?? []; @@ -150,7 +145,7 @@ class Minz_Url { /** * Returns an array representing the URL as passed in the address bar - * @return array> URL representation + * @return array{'c'?:string,'a'?:string,'params'?:array} URL representation */ public static function build(): array { $url = [ diff --git a/lib/Minz/View.php b/lib/Minz/View.php index 3b18c1dba..70b745ea4 100644 --- a/lib/Minz/View.php +++ b/lib/Minz/View.php @@ -22,7 +22,7 @@ class Minz_View { private static $title = ''; /** @var array */ private static $styles = []; - /** @var array */ + /** @var array */ private static $scripts = []; /** @var string|array{'dark'?:string,'light'?:string,'default'?:string} */ private static $themeColors; @@ -83,7 +83,7 @@ class Minz_View { * The file is searched inside list of $base_pathnames. * * @param string $filename the name of the file to include. - * @return boolean true if the file has been included, false else. + * @return bool true if the file has been included, false else. */ private function includeFile(string $filename): bool { // We search the filename in the list of base pathnames. Only the first view @@ -158,9 +158,9 @@ class Minz_View { /** * Choose the current view layout. - * @param string|false $layout the layout name to use, false to use no layouts. + * @param string|null $layout the layout name to use, false to use no layouts. */ - public function _layout($layout): void { + public function _layout(?string $layout): void { if ($layout) { $this->layout_filename = self::LAYOUT_PATH_NAME . $layout . '.phtml'; } else { @@ -178,7 +178,7 @@ class Minz_View { if ($use) { $this->_layout(self::LAYOUT_DEFAULT); } else { - $this->_layout(false); + $this->_layout(null); } } @@ -326,7 +326,6 @@ class Minz_View { /** * Management of parameters added to the view - * @param string $key * @param mixed $value */ public static function _param(string $key, $value): void { diff --git a/lib/lib_date.php b/lib/lib_date.php index 00356927f..d9e1610e6 100644 --- a/lib/lib_date.php +++ b/lib/lib_date.php @@ -34,7 +34,7 @@ example('PT6M/'); example('PT7S/'); example('P1DT1H/'); -function example($dateInterval) { +function example(string $dateInterval) { $dateIntervalArray = parseDateInterval($dateInterval); echo $dateInterval, "\t=>\t", $dateIntervalArray[0] == null ? 'null' : @date('c', $dateIntervalArray[0]), '/', @@ -84,7 +84,7 @@ function _dateRelative(?string $d1, ?string $d2): ?string { * @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(string $dateInterval) { +function parseDateInterval(string $dateInterval): array { $dateInterval = trim($dateInterval); $dateInterval = str_replace('--', '/', $dateInterval); $dateInterval = strtoupper($dateInterval); diff --git a/lib/lib_install.php b/lib/lib_install.php index 18f4a732a..23c902440 100644 --- a/lib/lib_install.php +++ b/lib/lib_install.php @@ -1,7 +1,7 @@ */ function checkRequirements(string $dbType = ''): array { @@ -76,7 +76,7 @@ function checkRequirements(string $dbType = ''): array { } function generateSalt(): string { - return sha1(uniqid('' . mt_rand(), true).implode('', stat(__FILE__))); + return sha1(uniqid('' . mt_rand(), true).implode('', stat(__FILE__) ?: [])); } function initDb(): string { @@ -88,10 +88,14 @@ function initDb(): string { $db['pdo_options'][PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION; $conf->db = $db; //TODO: Remove this Minz limitation "Indirect modification of overloaded property" + if (empty($db['type'])) { + $db['type'] = 'sqlite'; + } + //Attempt to auto-create database if it does not already exist if ($db['type'] !== 'sqlite') { Minz_ModelPdo::$usesSharedPdo = false; - $dbBase = isset($db['base']) ? $db['base'] : ''; + $dbBase = $db['base'] ?? ''; //For first connection, use default database for PostgreSQL, empty database for MySQL / MariaDB: $db['base'] = $db['type'] === 'pgsql' ? 'postgres' : ''; $conf->db = $db; diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 1babc8d63..22af2729b 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -132,11 +132,7 @@ function checkUrl(string $url, bool $fixScheme = true) { } } -/** - * @param string $text - * @return string - */ -function safe_ascii($text) { +function safe_ascii(string $text): string { return filter_var($text, FILTER_DEFAULT, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH) ?: ''; } @@ -154,12 +150,7 @@ if (function_exists('mb_convert_encoding')) { } } -/** - * @param string $text - * @param bool $extended - * @return string - */ -function escapeToUnicodeAlternative($text, $extended = true) { +function escapeToUnicodeAlternative(string $text, bool $extended = true): string { $text = htmlspecialchars_decode($text, ENT_QUOTES); //Problematic characters @@ -176,7 +167,8 @@ function escapeToUnicodeAlternative($text, $extended = true) { return trim(str_replace($problem, $replace, $text)); } -function format_number(float $n, int $precision = 0): string { +/** @param int|float $n */ +function format_number($n, int $precision = 0): string { // number_format does not seem to be Unicode-compatible return str_replace(' ', ' ', // Thin non-breaking space number_format($n, $precision, '.', ' ') @@ -255,7 +247,7 @@ function sensitive_log($log) { /** * @param array $attributes */ -function customSimplePie($attributes = array()): SimplePie { +function customSimplePie(array $attributes = array()): SimplePie { if (FreshRSS_Context::$system_conf === null) { throw new FreshRSS_Context_Exception('System configuration not initialised!'); } @@ -339,10 +331,8 @@ function customSimplePie($attributes = array()): SimplePie { return $simplePie; } -/** - * @param string $data - */ -function sanitizeHTML($data, string $base = '', ?int $maxLength = null): string { +/** @param string $data */ +function sanitizeHTML(string $data, string $base = '', ?int $maxLength = null): string { if (!is_string($data) || ($maxLength !== null && $maxLength <= 0)) { return ''; } @@ -579,7 +569,7 @@ function listUsers(): array { * Return if the maximum number of registrations has been reached. * Note a max_registrations of 0 means there is no limit. * - * @return boolean true if number of users >= max registrations, false else. + * @return bool true if number of users >= max registrations, false else. */ function max_registrations_reached(): bool { if (FreshRSS_Context::$system_conf === null) { @@ -601,13 +591,13 @@ function max_registrations_reached(): bool { * @param string $username the name of the user of which we want the configuration. * @return FreshRSS_UserConfiguration|null object, or null if the configuration cannot be loaded. */ -function get_user_configuration(string $username) { +function get_user_configuration(string $username): ?FreshRSS_UserConfiguration { if (!FreshRSS_user_Controller::checkUsername($username)) { return null; } $namespace = 'user_' . $username; try { - Minz_Configuration::register($namespace, + FreshRSS_UserConfiguration::register($namespace, USERS_PATH . '/' . $username . '/config.php', FRESHRSS_PATH . '/config-user.default.php'); } catch (Minz_ConfigurationNamespaceException $e) { @@ -618,10 +608,7 @@ function get_user_configuration(string $username) { return null; } - /** - * @var FreshRSS_UserConfiguration $user_conf - */ - $user_conf = Minz_Configuration::get($namespace); + $user_conf = FreshRSS_UserConfiguration::get($namespace); return $user_conf; } @@ -644,7 +631,7 @@ function ipToBits(string $ip): string { * * @param string $ip the IP that we want to verify (ex: 192.168.16.1) * @param string $range the range to check against (ex: 192.168.16.0/24) - * @return boolean true if the IP is in the range, otherwise false + * @return bool true if the IP is in the range, otherwise false */ function checkCIDR(string $ip, string $range): bool { $binary_ip = ipToBits($ip); @@ -663,7 +650,7 @@ function checkCIDR(string $ip, string $range): bool { * This uses the REMOTE_ADDR header to determine the sender's IP * and the configuration option "trusted_sources" to get an array of the authorized ranges * - * @return boolean, true if the sender's IP is in one of the ranges defined in the configuration, else false + * @return bool, true if the sender's IP is in one of the ranges defined in the configuration, else false */ function checkTrustedIP(): bool { if (FreshRSS_Context::$system_conf === null) { @@ -840,7 +827,7 @@ const SHORTCUT_KEYS = [ function getNonStandardShortcuts(array $shortcuts): array { $standard = strtolower(implode(' ', SHORTCUT_KEYS)); - $nonStandard = array_filter($shortcuts, function ($shortcut) use ($standard) { + $nonStandard = array_filter($shortcuts, static function (string $shortcut) use ($standard) { $shortcut = trim($shortcut); return $shortcut !== '' & stripos($standard, $shortcut) === false; }); diff --git a/p/api/fever.php b/p/api/fever.php index 1d3fa6f05..26efe841b 100644 --- a/p/api/fever.php +++ b/p/api/fever.php @@ -336,9 +336,8 @@ final class FeverAPI $groups = array(); $categoryDAO = FreshRSS_Factory::createCategoryDao(); - $categories = $categoryDAO->listCategories(false, false); + $categories = $categoryDAO->listCategories(false, false) ?: []; - /** @var FreshRSS_Category $category */ foreach ($categories as $category) { $groups[] = array( 'id' => $category->id(), @@ -430,28 +429,28 @@ final class FeverAPI } /** - * @return integer|false + * @return int|false */ private function setItemAsRead(string $id) { return $this->entryDAO->markRead($id, true); } /** - * @return integer|false + * @return int|false */ private function setItemAsUnread(string $id) { return $this->entryDAO->markRead($id, false); } /** - * @return integer|false + * @return int|false */ private function setItemAsSaved(string $id) { return $this->entryDAO->markFavorite($id, true); } /** - * @return integer|false + * @return int|false */ private function setItemAsUnsaved(string $id) { return $this->entryDAO->markFavorite($id, false); @@ -540,7 +539,7 @@ final class FeverAPI } /** - * @return integer|false + * @return int|false */ private function setFeedAsRead(int $id, int $before) { $before = $this->convertBeforeToId($before); @@ -548,7 +547,7 @@ final class FeverAPI } /** - * @return integer|false + * @return int|false */ private function setGroupAsRead(int $id, int $before) { $before = $this->convertBeforeToId($before); diff --git a/p/f.php b/p/f.php index 6e30b64b2..43905775a 100644 --- a/p/f.php +++ b/p/f.php @@ -5,7 +5,7 @@ require(LIB_PATH . '/favicons.php'); require(LIB_PATH . '/http-conditional.php'); function show_default_favicon(int $cacheSeconds = 3600): void { - $default_mtime = @filemtime(DEFAULT_FAVICON); + $default_mtime = @filemtime(DEFAULT_FAVICON) ?: 0; if (!httpConditional($default_mtime, $cacheSeconds, 2)) { header('Content-Type: image/x-icon'); header('Content-Disposition: inline; filename="default_favicon.ico"'); @@ -21,8 +21,8 @@ if (!ctype_xdigit($id)) { $txt = FAVICONS_DIR . $id . '.txt'; $ico = FAVICONS_DIR . $id . '.ico'; -$ico_mtime = @filemtime($ico); -$txt_mtime = @filemtime($txt); +$ico_mtime = @filemtime($ico) ?: 0; +$txt_mtime = @filemtime($txt) ?: 0; if ($ico_mtime == false || $ico_mtime < $txt_mtime || ($ico_mtime < time() - (mt_rand(15, 20) * 86400))) { if ($txt_mtime == false) { diff --git a/p/i/index.php b/p/i/index.php index 690b1b1b1..6814a224f 100644 --- a/p/i/index.php +++ b/p/i/index.php @@ -35,8 +35,8 @@ if (!file_exists($applied_migrations_path)) { require(LIB_PATH . '/http-conditional.php'); $currentUser = Minz_User::name(); $dateLastModification = $currentUser === null ? time() : max( - @filemtime(USERS_PATH . '/' . $currentUser . '/' . LOG_FILENAME), - @filemtime(DATA_PATH . '/config.php') + @filemtime(USERS_PATH . '/' . $currentUser . '/' . LOG_FILENAME) ?: 0, + @filemtime(DATA_PATH . '/config.php') ?: 0 ); if (httpConditional($dateLastModification, 0, 0, false, PHP_COMPRESSION, true)) { Minz_Session::init('FreshRSS'); diff --git a/phpstan.neon b/phpstan.neon index 846731c70..dd47c79ee 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,7 @@ parameters: # TODO: Increase rule-level https://phpstan.org/user-guide/rule-levels - level: 5 + level: 6 + treatPhpDocTypesAsCertain: false fileExtensions: - php - phtml @@ -9,14 +10,16 @@ parameters: excludePaths: analyse: - lib/marienfressinaud/* + - lib/phpgt/* - lib/phpmailer/* - lib/SimplePie/* + - vendor/* analyseAndScan: - .git/* - node_modules/* - # TODO: include tests - - tests/* - - vendor/* bootstrapFiles: - cli/_cli.php - lib/favicons.php +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon diff --git a/tests/app/Models/CategoryTest.php b/tests/app/Models/CategoryTest.php index 93fbdbc63..a438afe9e 100644 --- a/tests/app/Models/CategoryTest.php +++ b/tests/app/Models/CategoryTest.php @@ -2,23 +2,22 @@ class CategoryTest extends PHPUnit\Framework\TestCase { - public function test__construct_whenNoParameters_createsObjectWithDefaultValues() { + public function test__construct_whenNoParameters_createsObjectWithDefaultValues(): void { $category = new FreshRSS_Category(); $this->assertEquals(0, $category->id()); $this->assertEquals('', $category->name()); } /** - * @param string $input - * @param string $expected * @dataProvider provideValidNames */ - public function test_name_whenValidValue_storesModifiedValue($input, $expected) { + public function test_name_whenValidValue_storesModifiedValue(string $input, string $expected): void { $category = new FreshRSS_Category($input); $this->assertEquals($expected, $category->name()); } - public function provideValidNames() { + /** @return array */ + public function provideValidNames(): array { return array( array('', ''), array('this string does not need trimming', 'this string does not need trimming'), @@ -30,7 +29,7 @@ class CategoryTest extends PHPUnit\Framework\TestCase { ); } - public function test_feedOrdering() { + public function test_feedOrdering(): void { $feed_1 = $this->getMockBuilder(FreshRSS_Feed::class) ->disableOriginalConstructor() ->getMock(); diff --git a/tests/app/Models/LogDAOTest.php b/tests/app/Models/LogDAOTest.php index 18cad4968..abe6c6c1f 100644 --- a/tests/app/Models/LogDAOTest.php +++ b/tests/app/Models/LogDAOTest.php @@ -36,7 +36,7 @@ class LogDAOTest extends TestCase { $this->logDAO::truncate(self::LOG_FILE_TEST); - $this->assertStringContainsString('', file_get_contents($this->logPath)); + $this->assertStringContainsString('', file_get_contents($this->logPath) ?: ''); } protected function tearDown(): void { diff --git a/tests/app/Models/SearchTest.php b/tests/app/Models/SearchTest.php index 52c10244d..2b2501589 100644 --- a/tests/app/Models/SearchTest.php +++ b/tests/app/Models/SearchTest.php @@ -6,9 +6,8 @@ class SearchTest extends PHPUnit\Framework\TestCase { /** * @dataProvider provideEmptyInput - * @param string|null $input */ - public function test__construct_whenInputIsEmpty_getsOnlyNullValues($input) { + public function test__construct_whenInputIsEmpty_getsOnlyNullValues(?string $input): void { $search = new FreshRSS_Search($input); $this->assertEquals('', $search->getRawInput()); $this->assertNull($search->getIntitle()); @@ -24,9 +23,9 @@ class SearchTest extends PHPUnit\Framework\TestCase { /** * Return an array of values for the search object. * Here is the description of the values - * @return array + * @return array{array{''},array{null}} */ - public function provideEmptyInput() { + public function provideEmptyInput(): array { return array( array(''), array(null), @@ -35,20 +34,19 @@ class SearchTest extends PHPUnit\Framework\TestCase { /** * @dataProvider provideIntitleSearch - * @param string $input - * @param string $intitle_value - * @param string|null $search_value + * @param array|null $intitle_value + * @param array|null $search_value */ - public function test__construct_whenInputContainsIntitle_setsIntitleProperty($input, $intitle_value, $search_value) { + public function test__construct_whenInputContainsIntitle_setsIntitleProperty(string $input, ?array $intitle_value, ?array $search_value): void { $search = new FreshRSS_Search($input); $this->assertEquals($intitle_value, $search->getIntitle()); $this->assertEquals($search_value, $search->getSearch()); } /** - * @return array + * @return array> */ - public function provideIntitleSearch() { + public function provideIntitleSearch(): array { return array( array('intitle:word1', array('word1'), null), array('intitle:word1-word2', array('word1-word2'), null), @@ -73,20 +71,19 @@ class SearchTest extends PHPUnit\Framework\TestCase { /** * @dataProvider provideAuthorSearch - * @param string $input - * @param string $author_value - * @param string|null $search_value + * @param array|null $author_value + * @param array|null $search_value */ - public function test__construct_whenInputContainsAuthor_setsAuthorValue($input, $author_value, $search_value) { + public function test__construct_whenInputContainsAuthor_setsAuthorValue(string $input, ?array $author_value, ?array $search_value): void { $search = new FreshRSS_Search($input); $this->assertEquals($author_value, $search->getAuthor()); $this->assertEquals($search_value, $search->getSearch()); } /** - * @return array + * @return array> */ - public function provideAuthorSearch() { + public function provideAuthorSearch(): array { return array( array('author:word1', array('word1'), null), array('author:word1-word2', array('word1-word2'), null), @@ -111,20 +108,19 @@ class SearchTest extends PHPUnit\Framework\TestCase { /** * @dataProvider provideInurlSearch - * @param string $input - * @param string $inurl_value - * @param string|null $search_value + * @param array|null $inurl_value + * @param array|null $search_value */ - public function test__construct_whenInputContainsInurl_setsInurlValue($input, $inurl_value, $search_value) { + public function test__construct_whenInputContainsInurl_setsInurlValue(string $input, ?array $inurl_value, ?array $search_value): void { $search = new FreshRSS_Search($input); $this->assertEquals($inurl_value, $search->getInurl()); $this->assertEquals($search_value, $search->getSearch()); } /** - * @return array + * @return array> */ - public function provideInurlSearch() { + public function provideInurlSearch(): array { return array( array('inurl:word1', array('word1'), null), array('inurl: word1', array(), array('word1')), @@ -139,72 +135,65 @@ class SearchTest extends PHPUnit\Framework\TestCase { /** * @dataProvider provideDateSearch - * @param string $input - * @param string $min_date_value - * @param string $max_date_value */ - public function test__construct_whenInputContainsDate_setsDateValues($input, $min_date_value, $max_date_value) { + public function test__construct_whenInputContainsDate_setsDateValues(string $input, ?int $min_date_value, ?int $max_date_value): void { $search = new FreshRSS_Search($input); $this->assertEquals($min_date_value, $search->getMinDate()); $this->assertEquals($max_date_value, $search->getMaxDate()); } /** - * @return array + * @return array> */ - public function provideDateSearch() { + public function provideDateSearch(): array { return array( - array('date:2007-03-01T13:00:00Z/2008-05-11T15:30:00Z', '1172754000', '1210519800'), - array('date:2007-03-01T13:00:00Z/P1Y2M10DT2H30M', '1172754000', '1210519799'), - array('date:P1Y2M10DT2H30M/2008-05-11T15:30:00Z', '1172754001', '1210519800'), + array('date:2007-03-01T13:00:00Z/2008-05-11T15:30:00Z', 1172754000, 1210519800), + array('date:2007-03-01T13:00:00Z/P1Y2M10DT2H30M', 1172754000, 1210519799), + array('date:P1Y2M10DT2H30M/2008-05-11T15:30:00Z', 1172754001, 1210519800), array('date:2007-03-01/2008-05-11', strtotime('2007-03-01'), strtotime('2008-05-12') - 1), - array('date:2007-03-01/', strtotime('2007-03-01'), ''), - array('date:/2008-05-11', '', strtotime('2008-05-12') - 1), + array('date:2007-03-01/', strtotime('2007-03-01'), null), + array('date:/2008-05-11', null, strtotime('2008-05-12') - 1), ); } /** * @dataProvider providePubdateSearch - * @param string $input - * @param string $min_pubdate_value - * @param string $max_pubdate_value */ - public function test__construct_whenInputContainsPubdate_setsPubdateValues($input, $min_pubdate_value, $max_pubdate_value) { + public function test__construct_whenInputContainsPubdate_setsPubdateValues(string $input, ?int $min_pubdate_value, ?int $max_pubdate_value): void { $search = new FreshRSS_Search($input); $this->assertEquals($min_pubdate_value, $search->getMinPubdate()); $this->assertEquals($max_pubdate_value, $search->getMaxPubdate()); } /** - * @return array + * @return array> */ - public function providePubdateSearch() { + public function providePubdateSearch(): array { return array( - array('pubdate:2007-03-01T13:00:00Z/2008-05-11T15:30:00Z', '1172754000', '1210519800'), - array('pubdate:2007-03-01T13:00:00Z/P1Y2M10DT2H30M', '1172754000', '1210519799'), - array('pubdate:P1Y2M10DT2H30M/2008-05-11T15:30:00Z', '1172754001', '1210519800'), + array('pubdate:2007-03-01T13:00:00Z/2008-05-11T15:30:00Z', 1172754000, 1210519800), + array('pubdate:2007-03-01T13:00:00Z/P1Y2M10DT2H30M', 1172754000, 1210519799), + array('pubdate:P1Y2M10DT2H30M/2008-05-11T15:30:00Z', 1172754001, 1210519800), array('pubdate:2007-03-01/2008-05-11', strtotime('2007-03-01'), strtotime('2008-05-12') - 1), - array('pubdate:2007-03-01/', strtotime('2007-03-01'), ''), - array('pubdate:/2008-05-11', '', strtotime('2008-05-12') - 1), + array('pubdate:2007-03-01/', strtotime('2007-03-01'), null), + array('pubdate:/2008-05-11', null, strtotime('2008-05-12') - 1), ); } /** * @dataProvider provideTagsSearch - * @param string $input - * @param string $tags_value - * @param string|null $search_value + * @param array|null $tags_value + * @param array|null $search_value */ - public function test__construct_whenInputContainsTags_setsTagsValue($input, $tags_value, $search_value) { + public function test__construct_whenInputContainsTags_setsTagsValue(string $input, ?array $tags_value, ?array $search_value): void { $search = new FreshRSS_Search($input); $this->assertEquals($tags_value, $search->getTags()); $this->assertEquals($search_value, $search->getSearch()); } /** - * @return array + * @return array|null>> */ - public function provideTagsSearch() { + public function provideTagsSearch(): array { return array( array('#word1', array('word1'), null), array('# word1', array(), array('#', 'word1')), @@ -219,19 +208,15 @@ class SearchTest extends PHPUnit\Framework\TestCase { /** * @dataProvider provideMultipleSearch - * @param string $input - * @param string $author_value - * @param string $min_date_value - * @param string $max_date_value - * @param string $intitle_value - * @param string $inurl_value - * @param string $min_pubdate_value - * @param string $max_pubdate_value - * @param array $tags_value - * @param string|null $search_value + * @param array|null $author_value + * @param array $intitle_value + * @param array|null $inurl_value + * @param array|null $tags_value + * @param array|null $search_value */ - public function test__construct_whenInputContainsMultipleKeywords_setsValues($input, $author_value, $min_date_value, - $max_date_value, $intitle_value, $inurl_value, $min_pubdate_value, $max_pubdate_value, $tags_value, $search_value) { + public function test__construct_whenInputContainsMultipleKeywords_setsValues(string $input, ?array $author_value, ?int $min_date_value, + ?int $max_date_value, ?array $intitle_value, ?array $inurl_value, ?int $min_pubdate_value, + ?int $max_pubdate_value, ?array $tags_value, ?array $search_value): void { $search = new FreshRSS_Search($input); $this->assertEquals($author_value, $search->getAuthor()); $this->assertEquals($min_date_value, $search->getMinDate()); @@ -245,7 +230,8 @@ class SearchTest extends PHPUnit\Framework\TestCase { $this->assertEquals($input, $search->getRawInput()); } - public function provideMultipleSearch() { + /** @return array> */ + public function provideMultipleSearch(): array { return array( array( 'author:word1 date:2007-03-01/2008-05-11 intitle:word2 inurl:word3 pubdate:2007-03-01/2008-05-11 #word4 #word5', @@ -302,13 +288,14 @@ class SearchTest extends PHPUnit\Framework\TestCase { * @dataProvider provideParentheses * @param array $values */ - public function test__construct_parentheses(string $input, string $sql, $values) { + public function test__construct_parentheses(string $input, string $sql, array $values): void { list($filterValues, $filterSearch) = FreshRSS_EntryDAOPGSQL::sqlBooleanSearch('e.', new FreshRSS_BooleanSearch($input)); $this->assertEquals($sql, $filterSearch); $this->assertEquals($values, $filterValues); } - public function provideParentheses() { + /** @return array> */ + public function provideParentheses(): array { return [ [ 'f:1 (f:2 OR f:3 OR f:4) (f:5 OR (f:6 OR f:7))', diff --git a/tests/app/Models/UserQueryTest.php b/tests/app/Models/UserQueryTest.php index 7b1e88907..d8610a81b 100644 --- a/tests/app/Models/UserQueryTest.php +++ b/tests/app/Models/UserQueryTest.php @@ -5,21 +5,21 @@ */ class UserQueryTest extends PHPUnit\Framework\TestCase { - public function test__construct_whenAllQuery_storesAllParameters() { + public function test__construct_whenAllQuery_storesAllParameters(): void { $query = array('get' => 'a'); $user_query = new FreshRSS_UserQuery($query); $this->assertEquals('all', $user_query->getGetName()); $this->assertEquals('all', $user_query->getGetType()); } - public function test__construct_whenFavoriteQuery_storesFavoriteParameters() { + public function test__construct_whenFavoriteQuery_storesFavoriteParameters(): void { $query = array('get' => 's'); $user_query = new FreshRSS_UserQuery($query); $this->assertEquals('favorite', $user_query->getGetName()); $this->assertEquals('favorite', $user_query->getGetType()); } - public function test__construct_whenCategoryQueryAndNoDao_throwsException() { + public function test__construct_whenCategoryQueryAndNoDao_throwsException(): void { $this->expectException(FreshRSS_DAO_Exception::class); $this->expectExceptionMessage('Category DAO is not loaded in UserQuery'); @@ -27,13 +27,15 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { new FreshRSS_UserQuery($query); } - public function test__construct_whenCategoryQuery_storesCategoryParameters() { + public function test__construct_whenCategoryQuery_storesCategoryParameters(): void { $category_name = 'some category name'; + /** @var FreshRSS_Category&PHPUnit\Framework\MockObject\MockObject */ $cat = $this->createMock('FreshRSS_Category'); $cat->expects($this->atLeastOnce()) ->method('name') ->withAnyParameters() ->willReturn($category_name); + /** @var FreshRSS_CategoryDAO&PHPUnit\Framework\MockObject\MockObject */ $cat_dao = $this->createMock('FreshRSS_CategoryDAO'); $cat_dao->expects($this->atLeastOnce()) ->method('searchById') @@ -45,7 +47,7 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { $this->assertEquals('category', $user_query->getGetType()); } - public function test__construct_whenFeedQueryAndNoDao_throwsException() { + public function test__construct_whenFeedQueryAndNoDao_throwsException(): void { $this->expectException(FreshRSS_DAO_Exception::class); $this->expectExceptionMessage('Feed DAO is not loaded in UserQuery'); @@ -53,13 +55,15 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { new FreshRSS_UserQuery($query); } - public function test__construct_whenFeedQuery_storesFeedParameters() { + public function test__construct_whenFeedQuery_storesFeedParameters(): void { $feed_name = 'some feed name'; - $feed = $this->createMock('FreshRSS_Feed', array(), array('', false)); + /** @var FreshRSS_Feed&PHPUnit\Framework\MockObject\MockObject */ + $feed = $this->createMock('FreshRSS_Feed'); $feed->expects($this->atLeastOnce()) ->method('name') ->withAnyParameters() ->willReturn($feed_name); + /** @var FreshRSS_FeedDAO&PHPUnit\Framework\MockObject\MockObject */ $feed_dao = $this->createMock('FreshRSS_FeedDAO'); $feed_dao->expects($this->atLeastOnce()) ->method('searchById') @@ -71,48 +75,48 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { $this->assertEquals('feed', $user_query->getGetType()); } - public function test__construct_whenUnknownQuery_doesStoreParameters() { + public function test__construct_whenUnknownQuery_doesStoreParameters(): void { $query = array('get' => 'q'); $user_query = new FreshRSS_UserQuery($query); $this->assertEmpty($user_query->getGetName()); $this->assertEmpty($user_query->getGetType()); } - public function test__construct_whenName_storesName() { + public function test__construct_whenName_storesName(): void { $name = 'some name'; $query = array('name' => $name); $user_query = new FreshRSS_UserQuery($query); $this->assertEquals($name, $user_query->getName()); } - public function test__construct_whenOrder_storesOrder() { + public function test__construct_whenOrder_storesOrder(): void { $order = 'some order'; $query = array('order' => $order); $user_query = new FreshRSS_UserQuery($query); $this->assertEquals($order, $user_query->getOrder()); } - public function test__construct_whenState_storesState() { + public function test__construct_whenState_storesState(): void { $state = FreshRSS_Entry::STATE_ALL; $query = array('state' => $state); $user_query = new FreshRSS_UserQuery($query); $this->assertEquals($state, $user_query->getState()); } - public function test__construct_whenUrl_storesUrl() { + public function test__construct_whenUrl_storesUrl(): void { $url = 'some url'; $query = array('url' => $url); $user_query = new FreshRSS_UserQuery($query); $this->assertEquals($url, $user_query->getUrl()); } - public function testToArray_whenNoData_returnsEmptyArray() { + public function testToArray_whenNoData_returnsEmptyArray(): void { $user_query = new FreshRSS_UserQuery(array()); $this->assertIsIterable($user_query->toArray()); $this->assertCount(0, $user_query->toArray()); } - public function testToArray_whenData_returnsArray() { + public function testToArray_whenData_returnsArray(): void { $query = array( 'get' => 's', 'name' => 'some name', @@ -127,7 +131,7 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { $this->assertEquals($query, $user_query->toArray()); } - public function testHasSearch_whenSearch_returnsTrue() { + public function testHasSearch_whenSearch_returnsTrue(): void { $query = array( 'search' => 'some search', ); @@ -135,31 +139,33 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { $this->assertTrue($user_query->hasSearch()); } - public function testHasSearch_whenNoSearch_returnsFalse() { + public function testHasSearch_whenNoSearch_returnsFalse(): void { $user_query = new FreshRSS_UserQuery(array()); $this->assertFalse($user_query->hasSearch()); } - public function testHasParameters_whenAllQuery_returnsFalse() { + public function testHasParameters_whenAllQuery_returnsFalse(): void { $query = array('get' => 'a'); $user_query = new FreshRSS_UserQuery($query); $this->assertFalse($user_query->hasParameters()); } - public function testHasParameters_whenNoParameter_returnsFalse() { + public function testHasParameters_whenNoParameter_returnsFalse(): void { $query = array(); $user_query = new FreshRSS_UserQuery($query); $this->assertFalse($user_query->hasParameters()); } - public function testHasParameters_whenParameter_returnTrue() { + public function testHasParameters_whenParameter_returnTrue(): void { $query = array('get' => 's'); $user_query = new FreshRSS_UserQuery($query); $this->assertTrue($user_query->hasParameters()); } - public function testIsDeprecated_whenCategoryExists_returnFalse() { + public function testIsDeprecated_whenCategoryExists_returnFalse(): void { + /** @var FreshRSS_Category&PHPUnit\Framework\MockObject\MockObject */ $cat = $this->createMock('FreshRSS_Category'); + /** @var FreshRSS_CategoryDAO&PHPUnit\Framework\MockObject\MockObject */ $cat_dao = $this->createMock('FreshRSS_CategoryDAO'); $cat_dao->expects($this->atLeastOnce()) ->method('searchById') @@ -170,7 +176,8 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { $this->assertFalse($user_query->isDeprecated()); } - public function testIsDeprecated_whenCategoryDoesNotExist_returnTrue() { + public function testIsDeprecated_whenCategoryDoesNotExist_returnTrue(): void { + /** @var FreshRSS_CategoryDAO&PHPUnit\Framework\MockObject\MockObject */ $cat_dao = $this->createMock('FreshRSS_CategoryDAO'); $cat_dao->expects($this->atLeastOnce()) ->method('searchById') @@ -181,8 +188,10 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { $this->assertTrue($user_query->isDeprecated()); } - public function testIsDeprecated_whenFeedExists_returnFalse() { - $feed = $this->createMock('FreshRSS_Feed', array(), array('', false)); + public function testIsDeprecated_whenFeedExists_returnFalse(): void { + /** @var FreshRSS_Feed&PHPUnit\Framework\MockObject\MockObject */ + $feed = $this->createMock('FreshRSS_Feed'); + /** @var FreshRSS_FeedDAO&PHPUnit\Framework\MockObject\MockObject */ $feed_dao = $this->createMock('FreshRSS_FeedDAO'); $feed_dao->expects($this->atLeastOnce()) ->method('searchById') @@ -193,7 +202,8 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { $this->assertFalse($user_query->isDeprecated()); } - public function testIsDeprecated_whenFeedDoesNotExist_returnTrue() { + public function testIsDeprecated_whenFeedDoesNotExist_returnTrue(): void { + /** @var FreshRSS_FeedDAO&PHPUnit\Framework\MockObject\MockObject */ $feed_dao = $this->createMock('FreshRSS_FeedDAO'); $feed_dao->expects($this->atLeastOnce()) ->method('searchById') @@ -204,19 +214,19 @@ class UserQueryTest extends PHPUnit\Framework\TestCase { $this->assertTrue($user_query->isDeprecated()); } - public function testIsDeprecated_whenAllQuery_returnFalse() { + public function testIsDeprecated_whenAllQuery_returnFalse(): void { $query = array('get' => 'a'); $user_query = new FreshRSS_UserQuery($query); $this->assertFalse($user_query->isDeprecated()); } - public function testIsDeprecated_whenFavoriteQuery_returnFalse() { + public function testIsDeprecated_whenFavoriteQuery_returnFalse(): void { $query = array('get' => 's'); $user_query = new FreshRSS_UserQuery($query); $this->assertFalse($user_query->isDeprecated()); } - public function testIsDeprecated_whenUnknownQuery_returnFalse() { + public function testIsDeprecated_whenUnknownQuery_returnFalse(): void { $query = array('get' => 'q'); $user_query = new FreshRSS_UserQuery($query); $this->assertFalse($user_query->isDeprecated()); diff --git a/tests/app/Utils/passwordUtilTest.php b/tests/app/Utils/passwordUtilTest.php index ddccb784f..113476c63 100644 --- a/tests/app/Utils/passwordUtilTest.php +++ b/tests/app/Utils/passwordUtilTest.php @@ -1,7 +1,7 @@ assertTrue($ok); } - public function testCheckReturnsFalseIfEmpty() { + public function testCheckReturnsFalseIfEmpty(): void { $password = ''; $ok = FreshRSS_password_Util::check($password); @@ -17,7 +17,7 @@ class passwordUtilTest extends PHPUnit\Framework\TestCase { $this->assertFalse($ok); } - public function testCheckReturnsFalseIfLessThan7Characters() { + public function testCheckReturnsFalseIfLessThan7Characters(): void { $password = '123456'; $ok = FreshRSS_password_Util::check($password); diff --git a/tests/cli/i18n/I18nCompletionValidatorTest.php b/tests/cli/i18n/I18nCompletionValidatorTest.php index 1aa871f20..1a361823d 100644 --- a/tests/cli/i18n/I18nCompletionValidatorTest.php +++ b/tests/cli/i18n/I18nCompletionValidatorTest.php @@ -4,6 +4,7 @@ require_once __DIR__ . '/../../../cli/i18n/I18nCompletionValidator.php'; require_once __DIR__ . '/../../../cli/i18n/I18nValue.php'; class I18nCompletionValidatorTest extends PHPUnit\Framework\TestCase { + /** @var I18nValue&PHPUnit\Framework\MockObject\MockObject */ private $value; public function setUp(): void { @@ -12,7 +13,7 @@ class I18nCompletionValidatorTest extends PHPUnit\Framework\TestCase { ->getMock(); } - public function testDisplayReport() { + public function testDisplayReport(): void { $validator = new I18nCompletionValidator([], []); $this->assertEquals("There is no data.\n", $validator->displayReport()); @@ -40,13 +41,13 @@ class I18nCompletionValidatorTest extends PHPUnit\Framework\TestCase { $validator->displayReport(); } - public function testValidateWhenNoData() { + public function testValidateWhenNoData(): void { $validator = new I18nCompletionValidator([], []); $this->assertTrue($validator->validate()); $this->assertEquals('', $validator->displayResult()); } - public function testValidateWhenKeyIsMissing() { + public function testValidateWhenKeyIsMissing(): void { $validator = new I18nCompletionValidator([ 'file1.php' => [ 'file1.l1.l2.k1' => $this->value, @@ -60,7 +61,7 @@ class I18nCompletionValidatorTest extends PHPUnit\Framework\TestCase { $this->assertEquals("Missing key file1.l1.l2.k1\nMissing key file2.l1.l2.k1\n", $validator->displayResult()); } - public function testValidateWhenKeyIsIgnored() { + public function testValidateWhenKeyIsIgnored(): void { $this->value->expects($this->exactly(2)) ->method('isIgnore') ->willReturn(true); @@ -85,7 +86,7 @@ class I18nCompletionValidatorTest extends PHPUnit\Framework\TestCase { $this->assertEquals('', $validator->displayResult()); } - public function testValidateWhenValueIsEqual() { + public function testValidateWhenValueIsEqual(): void { $this->value->expects($this->exactly(2)) ->method('isIgnore') ->willReturn(false); @@ -113,7 +114,7 @@ class I18nCompletionValidatorTest extends PHPUnit\Framework\TestCase { $this->assertEquals("Untranslated key file1.l1.l2.k1 - \nUntranslated key file2.l1.l2.k1 - \n", $validator->displayResult()); } - public function testValidateWhenValueIsDifferent() { + public function testValidateWhenValueIsDifferent(): void { $this->value->expects($this->exactly(2)) ->method('isIgnore') ->willReturn(false); diff --git a/tests/cli/i18n/I18nDataTest.php b/tests/cli/i18n/I18nDataTest.php index b27ad830c..37811c193 100644 --- a/tests/cli/i18n/I18nDataTest.php +++ b/tests/cli/i18n/I18nDataTest.php @@ -4,7 +4,9 @@ require_once __DIR__ . '/../../../cli/i18n/I18nData.php'; require_once __DIR__ . '/../../../cli/i18n/I18nValue.php'; class I18nDataTest extends PHPUnit\Framework\TestCase { + /** @var array>> */ private $referenceData; + /** @var I18nValue&PHPUnit\Framework\MockObject\MockObject */ private $value; public function setUp(): void { @@ -31,12 +33,12 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ]; } - public function testConstructWhenReferenceOnly() { + public function testConstructWhenReferenceOnly(): void { $data = new I18nData($this->referenceData); $this->assertEquals($this->referenceData, $data->getData()); } - public function testConstructorWhenLanguageIsMissingFile() { + public function testConstructorWhenLanguageIsMissingFile(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [ 'file1.php' => [ @@ -79,7 +81,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getData()); } - public function testConstructorWhenLanguageIsMissingKeys() { + public function testConstructorWhenLanguageIsMissingKeys(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [ 'file1.php' => [ @@ -125,7 +127,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getData()); } - public function testConstructorWhenLanguageHasExtraKeys() { + public function testConstructorWhenLanguageHasExtraKeys(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [ 'file1.php' => [ @@ -179,7 +181,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getData()); } - public function testConstructorWhenValueIsIdenticalAndIsMarkedAsIgnore() { + public function testConstructorWhenValueIsIdenticalAndIsMarkedAsIgnore(): void { $value = $this->getMockBuilder(I18nValue::class) ->disableOriginalConstructor() ->getMock(); @@ -204,7 +206,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { new I18nData($rawData); } - public function testConstructorWhenValueIsIdenticalAndIsNotMarkedAsIgnore() { + public function testConstructorWhenValueIsIdenticalAndIsNotMarkedAsIgnore(): void { $value = $this->getMockBuilder(I18nValue::class) ->disableOriginalConstructor() ->getMock(); @@ -229,7 +231,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { new I18nData($rawData); } - public function testConstructorWhenValueIsDifferentAndIsMarkedAsToDo() { + public function testConstructorWhenValueIsDifferentAndIsMarkedAsToDo(): void { $value = $this->getMockBuilder(I18nValue::class) ->disableOriginalConstructor() ->getMock(); @@ -249,7 +251,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { new I18nData($rawData); } - public function testConstructorWhenValueIsDifferentAndIsNotMarkedAsTodo() { + public function testConstructorWhenValueIsDifferentAndIsNotMarkedAsTodo(): void { $value = $this->getMockBuilder(I18nValue::class) ->disableOriginalConstructor() ->getMock(); @@ -269,7 +271,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { new I18nData($rawData); } - public function testGetAvailableLanguagesWhenTheyAreSorted() { + public function testGetAvailableLanguagesWhenTheyAreSorted(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [], 'nl' => [], @@ -282,7 +284,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getAvailableLanguages()); } - public function testGetAvailableLanguagesWhenTheyAreNotSorted() { + public function testGetAvailableLanguagesWhenTheyAreNotSorted(): void { $rawData = array_merge($this->referenceData, [ 'nl' => [], 'fr' => [], @@ -297,14 +299,14 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getAvailableLanguages()); } - public function testAddLanguageWhenLanguageExists() { + public function testAddLanguageWhenLanguageExists(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('The selected language already exist.'); $data = new I18nData($this->referenceData); $data->addLanguage('en'); } - public function testAddLanguageWhenNoReferenceProvided() { + public function testAddLanguageWhenNoReferenceProvided(): void { $data = new I18nData($this->referenceData); $data->addLanguage('fr'); $this->assertEquals([ @@ -341,7 +343,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getData()); } - public function testAddLanguageWhenUnknownReferenceProvided() { + public function testAddLanguageWhenUnknownReferenceProvided(): void { $data = new I18nData($this->referenceData); $data->addLanguage('fr', 'unknown'); $this->assertEquals([ @@ -378,7 +380,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getData()); } - public function testAddLanguageWhenKnownReferenceProvided() { + public function testAddLanguageWhenKnownReferenceProvided(): void { $data = new I18nData($this->referenceData); $data->addLanguage('fr', 'en'); $this->assertEquals([ @@ -415,24 +417,24 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getData()); } - public function testIsKnownWhenKeyExists() { + public function testIsKnownWhenKeyExists(): void { $data = new I18nData($this->referenceData); $this->assertTrue($data->isKnown('file2.l1.l2.k2')); } - public function testIsKnownWhenKeyDoesNotExist() { + public function testIsKnownWhenKeyDoesNotExist(): void { $data = new I18nData($this->referenceData); $this->assertFalse($data->isKnown('file2.l1.l2.k3')); } - public function testAddKeyWhenKeyExists() { + public function testAddKeyWhenKeyExists(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('The selected key already exist.'); $data = new I18nData($this->referenceData); $data->addKey('file2.l1.l2.k1', 'value'); } - public function testAddKeyWhenParentKeyExists() { + public function testAddKeyWhenParentKeyExists(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [], ]); @@ -447,7 +449,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { $this->assertTrue($data->isKnown('file2.l1.l2.k1.sk1')); } - public function testAddKeyWhenKeyIsParent() { + public function testAddKeyWhenKeyIsParent(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [], ]); @@ -462,7 +464,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { $this->assertTrue($data->isKnown('file1.l1.l2.k2')); } - public function testAddKey() { + public function testAddKey(): void { $getTargetedValue = static function (I18nData $data, string $language) { return $data->getData()[$language]['file2.php']['file2.l1.l2.k3']; }; @@ -484,21 +486,21 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { $this->assertEquals($frValue, $enValue); } - public function testAddValueWhenLanguageDoesNotExist() { + public function testAddValueWhenLanguageDoesNotExist(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('The selected language does not exist.'); $data = new I18nData($this->referenceData); $data->addValue('file2.l1.l2.k2', 'new value', 'fr'); } - public function testAddValueWhenKeyDoesNotExist() { + public function testAddValueWhenKeyDoesNotExist(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('The selected key does not exist for the selected language.'); $data = new I18nData($this->referenceData); $data->addValue('unknown key', 'new value', 'en'); } - public function testAddValueWhenLanguageIsReferenceAndValueInOtherLanguageHasNotChange() { + public function testAddValueWhenLanguageIsReferenceAndValueInOtherLanguageHasNotChange(): void { $getTargetedValue = static function (I18nData $data, string $language) { return $data->getData()[$language]['file2.php']['file2.l1.l2.k2']; }; @@ -526,7 +528,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { $this->assertEquals('new value', $afterFrValue->getValue()); } - public function testAddValueWhenLanguageIsReferenceAndValueInOtherLanguageHasChange() { + public function testAddValueWhenLanguageIsReferenceAndValueInOtherLanguageHasChange(): void { $getTargetedValue = static function (I18nData $data, string $language) { return $data->getData()[$language]['file2.php']['file2.l1.l2.k2']; }; @@ -561,7 +563,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { $this->assertEquals($value, $afterFrValue); } - public function testAddValueWhenLanguageIsNotReference() { + public function testAddValueWhenLanguageIsNotReference(): void { $getTargetedValue = static function (I18nData $data, string $language) { return $data->getData()[$language]['file2.php']['file2.l1.l2.k2']; }; @@ -583,21 +585,21 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { $this->assertEquals('new value', $afterFrValue->getValue()); } - public function testRemoveKeyWhenKeyDoesNotExist() { + public function testRemoveKeyWhenKeyDoesNotExist(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('The selected key does not exist.'); $data = new I18nData($this->referenceData); $data->removeKey('Unknown key'); } - public function testRemoveKeyWhenKeyHasNoEmptySibling() { + public function testRemoveKeyWhenKeyHasNoEmptySibling(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('The selected key does not exist.'); $data = new I18nData($this->referenceData); $data->removeKey('file1.l1.l2'); } - public function testRemoveKeyWhenKeyIsEmptySibling() { + public function testRemoveKeyWhenKeyIsEmptySibling(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [], ]); @@ -635,7 +637,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getData()); } - public function testRemoveKeyWhenKeyIsTheOnlyChild() { + public function testRemoveKeyWhenKeyIsTheOnlyChild(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [], ]); @@ -673,7 +675,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { ], $data->getData()); } - public function testIgnore() { + public function testIgnore(): void { $value = $this->getMockBuilder(I18nValue::class) ->disableOriginalConstructor() ->getMock(); @@ -695,7 +697,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { $data->ignore('file1.l1.l2.k1', 'fr', false); } - public function testIgnoreUnmodified() { + public function testIgnoreUnmodified(): void { $value = $this->getMockBuilder(I18nValue::class) ->disableOriginalConstructor() ->getMock(); @@ -722,7 +724,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { $data->ignore_unmodified('fr', false); } - public function testGetLanguage() { + public function testGetLanguage(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [], 'nl' => [], @@ -731,7 +733,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase { $this->assertEquals($this->referenceData['en'], $data->getLanguage('en')); } - public function testGetReferenceLanguage() { + public function testGetReferenceLanguage(): void { $rawData = array_merge($this->referenceData, [ 'fr' => [], 'nl' => [], diff --git a/tests/cli/i18n/I18nFileTest.php b/tests/cli/i18n/I18nFileTest.php index 26566ddf1..662c14608 100644 --- a/tests/cli/i18n/I18nFileTest.php +++ b/tests/cli/i18n/I18nFileTest.php @@ -3,7 +3,7 @@ require_once __DIR__ . '/../../../cli/i18n/I18nFile.php'; class I18nFileTest extends PHPUnit\Framework\TestCase { - public function test() { + public function test(): void { $before = $this->computeFilesHash(); $file = new I18nFile(); @@ -15,7 +15,8 @@ class I18nFileTest extends PHPUnit\Framework\TestCase { $this->assertEquals($before, $after); } - private function computeFilesHash() { + /** @return array */ + private function computeFilesHash(): array { $hashes = []; $dirs = new DirectoryIterator(I18N_PATH); diff --git a/tests/cli/i18n/I18nUsageValidatorTest.php b/tests/cli/i18n/I18nUsageValidatorTest.php index 531e77c5d..fdd75bf64 100644 --- a/tests/cli/i18n/I18nUsageValidatorTest.php +++ b/tests/cli/i18n/I18nUsageValidatorTest.php @@ -4,6 +4,7 @@ require_once __DIR__ . '/../../../cli/i18n/I18nValue.php'; require_once __DIR__ . '/../../../cli/i18n/I18nUsageValidator.php'; class I18nUsageValidatorTest extends PHPUnit\Framework\TestCase { + /** @var I18nValue */ private $value; public function setUp(): void { @@ -12,7 +13,7 @@ class I18nUsageValidatorTest extends PHPUnit\Framework\TestCase { ->getMock(); } - public function testDisplayReport() { + public function testDisplayReport(): void { $validator = new I18nUsageValidator([], []); $this->assertEquals("There is no data.\n", $validator->displayReport()); @@ -40,13 +41,13 @@ class I18nUsageValidatorTest extends PHPUnit\Framework\TestCase { $validator->displayReport(); } - public function testValidateWhenNoData() { + public function testValidateWhenNoData(): void { $validator = new I18nUsageValidator([], []); $this->assertTrue($validator->validate()); $this->assertEquals('', $validator->displayResult()); } - public function testValidateWhenParentKeyExistsWithoutTransformation() { + public function testValidateWhenParentKeyExistsWithoutTransformation(): void { $validator = new I18nUsageValidator([ 'file1' => [ 'file1.l1.l2._' => $this->value, @@ -62,7 +63,7 @@ class I18nUsageValidatorTest extends PHPUnit\Framework\TestCase { $this->assertEquals('', $validator->displayResult()); } - public function testValidateWhenParentKeyExistsWithTransformation() { + public function testValidateWhenParentKeyExistsWithTransformation(): void { $validator = new I18nUsageValidator([ 'file1' => [ 'file1.l1.l2._' => $this->value, @@ -78,7 +79,7 @@ class I18nUsageValidatorTest extends PHPUnit\Framework\TestCase { $this->assertEquals('', $validator->displayResult()); } - public function testValidateWhenParentKeyDoesNotExist() { + public function testValidateWhenParentKeyDoesNotExist(): void { $validator = new I18nUsageValidator([ 'file1' => [ 'file1.l1.l2._' => $this->value, @@ -91,7 +92,7 @@ class I18nUsageValidatorTest extends PHPUnit\Framework\TestCase { $this->assertEquals("Unused key file1.l1.l2._ - \nUnused key file2.l1.l2._ - \n", $validator->displayResult()); } - public function testValidateWhenChildKeyExists() { + public function testValidateWhenChildKeyExists(): void { $validator = new I18nUsageValidator([ 'file1' => [ 'file1.l1.l2.k1' => $this->value, @@ -107,7 +108,7 @@ class I18nUsageValidatorTest extends PHPUnit\Framework\TestCase { $this->assertEquals('', $validator->displayResult()); } - public function testValidateWhenChildKeyDoesNotExist() { + public function testValidateWhenChildKeyDoesNotExist(): void { $validator = new I18nUsageValidator([ 'file1' => [ 'file1.l1.l2.k1' => $this->value, diff --git a/tests/cli/i18n/I18nValueTest.php b/tests/cli/i18n/I18nValueTest.php index cabc8e072..7a1109a20 100644 --- a/tests/cli/i18n/I18nValueTest.php +++ b/tests/cli/i18n/I18nValueTest.php @@ -3,35 +3,35 @@ require_once __DIR__ . '/../../../cli/i18n/I18nValue.php'; class I18nValueTest extends PHPUnit\Framework\TestCase { - public function testConstructorWithoutState() { + public function testConstructorWithoutState(): void { $value = new I18nValue('some value'); $this->assertEquals('some value', $value->getValue()); $this->assertFalse($value->isIgnore()); $this->assertFalse($value->isTodo()); } - public function testConstructorWithUnknownState() { + public function testConstructorWithUnknownState(): void { $value = new I18nValue('some value -> unknown'); $this->assertEquals('some value', $value->getValue()); $this->assertFalse($value->isIgnore()); $this->assertFalse($value->isTodo()); } - public function testConstructorWithTodoState() { + public function testConstructorWithTodoState(): void { $value = new I18nValue('some value -> todo'); $this->assertEquals('some value', $value->getValue()); $this->assertFalse($value->isIgnore()); $this->assertTrue($value->isTodo()); } - public function testConstructorWithIgnoreState() { + public function testConstructorWithIgnoreState(): void { $value = new I18nValue('some value -> ignore'); $this->assertEquals('some value', $value->getValue()); $this->assertTrue($value->isIgnore()); $this->assertFalse($value->isTodo()); } - public function testClone() { + public function testClone(): void { $value = new I18nValue('some value'); $clonedValue = clone $value; $this->assertEquals('some value', $value->getValue()); @@ -42,21 +42,21 @@ class I18nValueTest extends PHPUnit\Framework\TestCase { $this->assertTrue($clonedValue->isTodo()); } - public function testEqualWhenValueIsIdentical() { + public function testEqualWhenValueIsIdentical(): void { $value = new I18nValue('some value'); $clonedValue = clone $value; $this->assertTrue($value->equal($clonedValue)); $this->assertTrue($clonedValue->equal($value)); } - public function testEqualWhenValueIsDifferent() { + public function testEqualWhenValueIsDifferent(): void { $value = new I18nValue('some value'); $otherValue = new I18nValue('some other value'); $this->assertFalse($value->equal($otherValue)); $this->assertFalse($otherValue->equal($value)); } - public function testStates() { + public function testStates(): void { $reflectionProperty = new ReflectionProperty(I18nValue::class, 'state'); $reflectionProperty->setAccessible(true); @@ -74,7 +74,7 @@ class I18nValueTest extends PHPUnit\Framework\TestCase { $this->assertEquals('todo', $reflectionProperty->getValue($value)); } - public function testToString() { + public function testToString(): void { $value = new I18nValue('some value'); $this->assertEquals('some value', $value->__toString()); $value->markAsTodo(); diff --git a/tests/fixtures/migrations/2019_12_22_FooBar.php b/tests/fixtures/migrations/2019_12_22_FooBar.php index 4568ea8c9..21f673213 100644 --- a/tests/fixtures/migrations/2019_12_22_FooBar.php +++ b/tests/fixtures/migrations/2019_12_22_FooBar.php @@ -2,9 +2,9 @@ class FreshRSS_Migration_2019_12_22_FooBar { /** - * @return boolean true if the migration was successful, false otherwise + * @return bool true if the migration was successful, false otherwise */ - public static function migrate() { + public static function migrate(): bool { return true; } } diff --git a/tests/fixtures/migrations/2019_12_23_Baz.php b/tests/fixtures/migrations/2019_12_23_Baz.php index c13b2a814..056b0836c 100644 --- a/tests/fixtures/migrations/2019_12_23_Baz.php +++ b/tests/fixtures/migrations/2019_12_23_Baz.php @@ -2,9 +2,9 @@ class FreshRSS_Migration_2019_12_23_Baz { /** - * @return boolean true if the migration was successful, false otherwise + * @return bool true if the migration was successful, false otherwise */ - public static function migrate() { + public static function migrate(): bool { return true; } } diff --git a/tests/fixtures/migrations_with_failing/2020_01_11_FooBar.php b/tests/fixtures/migrations_with_failing/2020_01_11_FooBar.php index cdc2dd2c8..2edc79964 100644 --- a/tests/fixtures/migrations_with_failing/2020_01_11_FooBar.php +++ b/tests/fixtures/migrations_with_failing/2020_01_11_FooBar.php @@ -2,9 +2,9 @@ class FreshRSS_Migration_2020_01_11_FooBar { /** - * @return boolean true if the migration was successful, false otherwise + * @return bool true if the migration was successful, false otherwise */ - public static function migrate() { + public static function migrate(): bool { return true; } } diff --git a/tests/fixtures/migrations_with_failing/2020_01_12_Baz.php b/tests/fixtures/migrations_with_failing/2020_01_12_Baz.php index cd8ff10f3..75f39f7b5 100644 --- a/tests/fixtures/migrations_with_failing/2020_01_12_Baz.php +++ b/tests/fixtures/migrations_with_failing/2020_01_12_Baz.php @@ -2,9 +2,9 @@ class FreshRSS_Migration_2020_01_12_Baz { /** - * @return boolean true if the migration was successful, false otherwise + * @return bool true if the migration was successful, false otherwise */ - public static function migrate() { + public static function migrate(): bool { return false; } } diff --git a/tests/lib/CssXPath/CssXPathTest.php b/tests/lib/CssXPath/CssXPathTest.php index c6fe24fc8..8d5a943ec 100644 --- a/tests/lib/CssXPath/CssXPathTest.php +++ b/tests/lib/CssXPath/CssXPathTest.php @@ -2,7 +2,7 @@ class CssXPathTest extends PHPUnit\Framework\TestCase { - public function testCssXPathTranslatorClassExists() { + public function testCssXPathTranslatorClassExists(): void { $this->assertTrue(class_exists('Gt\\CssXPath\\Translator')); } } diff --git a/tests/lib/Minz/MigratorTest.php b/tests/lib/Minz/MigratorTest.php index bcee45204..bd30ba87e 100644 --- a/tests/lib/Minz/MigratorTest.php +++ b/tests/lib/Minz/MigratorTest.php @@ -4,7 +4,7 @@ use PHPUnit\Framework\TestCase; class MigratorTest extends TestCase { - public function testAddMigration() { + public function testAddMigration(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('foo', function () { @@ -17,7 +17,7 @@ class MigratorTest extends TestCase $this->assertTrue($result); } - public function testAddMigrationFailsIfUncallableMigration() { + public function testAddMigrationFailsIfUncallableMigration(): void { $this->expectException(BadFunctionCallException::class); $this->expectExceptionMessage('foo migration cannot be called.'); @@ -25,7 +25,7 @@ class MigratorTest extends TestCase $migrator->addMigration('foo', null); } - public function testMigrationsIsSorted() { + public function testMigrationsIsSorted(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('2_foo', function () { return true; @@ -43,7 +43,7 @@ class MigratorTest extends TestCase $this->assertSame($expected_versions, array_keys($migrations)); } - public function testSetAppliedVersions() { + public function testSetAppliedVersions(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('foo', function () { return true; @@ -54,7 +54,7 @@ class MigratorTest extends TestCase $this->assertSame(['foo'], $migrator->appliedVersions()); } - public function testSetAppliedVersionsTrimArgument() { + public function testSetAppliedVersionsTrimArgument(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('foo', function () { return true; @@ -65,7 +65,7 @@ class MigratorTest extends TestCase $this->assertSame(['foo'], $migrator->appliedVersions()); } - public function testSetAppliedVersionsFailsIfMigrationDoesNotExist() { + public function testSetAppliedVersionsFailsIfMigrationDoesNotExist(): void { $this->expectException(DomainException::class); $this->expectExceptionMessage('foo migration does not exist.'); @@ -74,7 +74,7 @@ class MigratorTest extends TestCase $migrator->setAppliedVersions(['foo']); } - public function testVersions() { + public function testVersions(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('foo', function () { return true; @@ -88,7 +88,7 @@ class MigratorTest extends TestCase $this->assertSame(['bar', 'foo'], $versions); } - public function testMigrate() { + public function testMigrate(): void { $migrator = new Minz_Migrator(); $spy = false; $migrator->addMigration('foo', function () use (&$spy) { @@ -106,7 +106,7 @@ class MigratorTest extends TestCase ], $result); } - public function testMigrateCallsMigrationsInSortedOrder() { + public function testMigrateCallsMigrationsInSortedOrder(): void { $migrator = new Minz_Migrator(); $spy_foo_1_is_called = false; $migrator->addMigration('2_foo', function () use (&$spy_foo_1_is_called) { @@ -126,7 +126,7 @@ class MigratorTest extends TestCase ], $result); } - public function testMigrateDoesNotCallAppliedMigrations() { + public function testMigrateDoesNotCallAppliedMigrations(): void { $migrator = new Minz_Migrator(); $spy = false; $migrator->addMigration('1_foo', function () use (&$spy) { @@ -141,7 +141,7 @@ class MigratorTest extends TestCase $this->assertSame([], $result); } - public function testMigrateCallNonAppliedBetweenTwoApplied() { + public function testMigrateCallNonAppliedBetweenTwoApplied(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('1_foo', function () { return true; @@ -162,7 +162,7 @@ class MigratorTest extends TestCase ], $result); } - public function testMigrateWithMigrationReturningFalseDoesNotApplyVersion() { + public function testMigrateWithMigrationReturningFalseDoesNotApplyVersion(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('1_foo', function () { return true; @@ -180,7 +180,7 @@ class MigratorTest extends TestCase ], $result); } - public function testMigrateWithMigrationReturningFalseDoesNotExecuteNextMigrations() { + public function testMigrateWithMigrationReturningFalseDoesNotExecuteNextMigrations(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('1_foo', function () { return false; @@ -200,7 +200,7 @@ class MigratorTest extends TestCase ], $result); } - public function testMigrateWithFailingMigration() { + public function testMigrateWithFailingMigration(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('foo', function () { throw new \Exception('Oops, it failed.'); @@ -214,7 +214,7 @@ class MigratorTest extends TestCase ], $result); } - public function testUpToDate() { + public function testUpToDate(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('foo', function () { return true; @@ -226,7 +226,7 @@ class MigratorTest extends TestCase $this->assertTrue($upToDate); } - public function testUpToDateIfRemainingMigration() { + public function testUpToDateIfRemainingMigration(): void { $migrator = new Minz_Migrator(); $migrator->addMigration('1_foo', function () { return true; @@ -241,7 +241,7 @@ class MigratorTest extends TestCase $this->assertFalse($upToDate); } - public function testUpToDateIfNoMigrations() { + public function testUpToDateIfNoMigrations(): void { $migrator = new Minz_Migrator(); $upToDate = $migrator->upToDate(); @@ -249,7 +249,7 @@ class MigratorTest extends TestCase $this->assertTrue($upToDate); } - public function testConstructorLoadsDirectory() { + public function testConstructorLoadsDirectory(): void { $migrations_path = TESTS_PATH . '/fixtures/migrations/'; $migrator = new Minz_Migrator($migrations_path); $expected_versions = ['2019_12_22_FooBar', '2019_12_23_Baz']; @@ -259,7 +259,7 @@ class MigratorTest extends TestCase $this->assertSame($expected_versions, array_keys($migrations)); } - public function testExecute() { + public function testExecute(): void { $migrations_path = TESTS_PATH . '/fixtures/migrations/'; $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); @@ -271,7 +271,7 @@ class MigratorTest extends TestCase @unlink($applied_migrations_path); } - public function testExecuteWithAlreadyAppliedMigration() { + public function testExecuteWithAlreadyAppliedMigration(): void { $migrations_path = TESTS_PATH . '/fixtures/migrations/'; $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); file_put_contents($applied_migrations_path, '2019_12_22_FooBar'); @@ -284,7 +284,7 @@ class MigratorTest extends TestCase @unlink($applied_migrations_path); } - public function testExecuteWithAppliedMigrationInDifferentOrder() { + public function testExecuteWithAppliedMigrationInDifferentOrder(): void { $migrations_path = TESTS_PATH . '/fixtures/migrations/'; $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); file_put_contents($applied_migrations_path, "2019_12_23_Baz\n2019_12_22_FooBar"); @@ -299,7 +299,7 @@ class MigratorTest extends TestCase @unlink($applied_migrations_path); } - public function testExecuteFailsIfVersionPathDoesNotExist() { + public function testExecuteFailsIfVersionPathDoesNotExist(): void { $migrations_path = TESTS_PATH . '/fixtures/migrations/'; $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); $expected_result = "Cannot open the {$applied_migrations_path} file"; @@ -311,7 +311,7 @@ class MigratorTest extends TestCase @unlink($applied_migrations_path); } - public function testExecuteFailsIfAMigrationIsFailing() { + public function testExecuteFailsIfAMigrationIsFailing(): void { $migrations_path = TESTS_PATH . '/fixtures/migrations_with_failing/'; $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); $expected_result = 'A migration failed to be applied, please see previous logs.'; diff --git a/tests/lib/PHPMailer/PHPMailerTest.php b/tests/lib/PHPMailer/PHPMailerTest.php index 8fc14b815..b39cf2cb0 100644 --- a/tests/lib/PHPMailer/PHPMailerTest.php +++ b/tests/lib/PHPMailer/PHPMailerTest.php @@ -2,7 +2,7 @@ class PHPMailerTest extends PHPUnit\Framework\TestCase { - public function testPHPMailerClassExists() { + public function testPHPMailerClassExists(): void { $this->assertTrue(class_exists('PHPMailer\\PHPMailer\\PHPMailer')); } } diff --git a/tests/phpstan-next.txt b/tests/phpstan-next.txt index 5b5b33e45..e2e081ecf 100644 --- a/tests/phpstan-next.txt +++ b/tests/phpstan-next.txt @@ -1,10 +1,48 @@ -# List of files, which are not yet passing PHPStan level 6 https://phpstan.org/user-guide/rule-levels -# https://github.com/FreshRSS/FreshRSS/issues/4112 +# List of files, which are not yet passing PHPStan level 7 https://phpstan.org/user-guide/rule-levels # Used for automated tests to avoid regressions in files already passing that level. # Can be regenerated with something like: -# find . -type d -name 'vendor' -prune -o -name '*.php' -exec sh -c 'vendor/bin/phpstan analyse --level 6 --memory-limit 512M {} >/dev/null 2>/dev/null || echo {}' \; +# find . -type d -name 'vendor' -prune -o -name '*.php' -exec sh -c 'vendor/bin/phpstan analyse --level 7 --memory-limit 512M {} >/dev/null 2>/dev/null || echo {}' \; -./app/install.php +./app/Controllers/configureController.php +./app/Controllers/feedController.php +./app/Controllers/importExportController.php +./app/Controllers/indexController.php +./app/Controllers/updateController.php +./app/Controllers/userController.php +./app/Models/CategoryDAO.php +./app/Models/Context.php +./app/Models/DatabaseDAO.php +./app/Models/DatabaseDAOPGSQL.php +./app/Models/Entry.php +./app/Models/EntryDAO.php ./app/Models/Feed.php +./app/Models/FeedDAO.php +./app/Models/ReadingMode.php +./app/Models/Search.php +./app/Models/Share.php +./app/Models/StatsDAO.php +./app/Models/TagDAO.php +./app/Models/Themes.php +./app/Models/UserQuery.php +./app/Services/ExportService.php ./app/Services/ImportService.php -./lib/Minz/Paginator.php +./app/views/helpers/logs_pagination.phtml +./app/views/index/reader.phtml +./app/views/stats/index.phtml +./app/views/stats/repartition.phtml +./app/views/user/details.phtml +./cli/check.translation.php +./cli/delete-user.php +./cli/do-install.php +./cli/manipulate.translation.php +./cli/user-info.php +./lib/lib_date.php +./lib/Minz/ActionController.php +./lib/Minz/Error.php +./lib/Minz/Mailer.php +./lib/Minz/Migrator.php +./lib/Minz/ModelPdo.php +./lib/Minz/Request.php +./p/api/greader.php +./tests/cli/i18n/I18nFileTest.php +./tests/lib/Minz/MigratorTest.php -- cgit v1.2.3