From 77e9877316fcfacb26799afdf32d94c8411da80e Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Fri, 31 Dec 2021 17:00:51 +0100 Subject: Add PHPStan (#4021) * Add PHPStan #fix https://github.com/FreshRSS/FreshRSS/issues/4016 https://phpstan.org/ ```sh composer run-script phpstan ``` * More fixes * Fix global variables * Add .phtml * Fix merge https://github.com/FreshRSS/FreshRSS/pull/4090 * Fix more warnings * Fix view errors and enable in CI * ReturnTypeWillChange * Dynamic view type * Fix Minz static/self bug --- .github/workflows/tests.yml | 3 + app/Controllers/authController.php | 8 +- app/Controllers/configureController.php | 21 +- app/Controllers/entryController.php | 9 +- app/Controllers/errorController.php | 2 +- app/Controllers/extensionController.php | 2 +- app/Controllers/feedController.php | 17 +- app/Controllers/importExportController.php | 9 +- app/Controllers/indexController.php | 20 +- app/Controllers/statsController.php | 10 +- app/Controllers/subscriptionController.php | 10 +- app/Controllers/tagController.php | 13 +- app/Controllers/updateController.php | 8 +- app/Controllers/userController.php | 13 +- app/FreshRSS.php | 12 +- app/Models/DatabaseDAO.php | 6 +- app/Models/EntryDAO.php | 2 +- app/Models/Search.php | 1 - app/Models/TagDAO.php | 2 +- app/Models/UserDAO.php | 5 +- app/Models/View.php | 119 +++++++++ app/SQL/install.sql.mysql.php | 14 +- app/SQL/install.sql.pgsql.php | 12 +- app/SQL/install.sql.sqlite.php | 12 +- app/Services/ExportService.php | 6 +- app/actualize_script.php | 28 +-- app/layout/aside_feed.phtml | 1 + app/layout/layout.phtml | 11 +- app/layout/simple.phtml | 11 +- app/views/auth/formLogin.phtml | 1 + app/views/auth/index.phtml | 5 +- app/views/auth/register.phtml | 1 + app/views/configure/archiving.phtml | 7 +- app/views/configure/display.phtml | 7 +- app/views/configure/integration.phtml | 7 +- app/views/configure/queries.phtml | 5 +- app/views/configure/query.phtml | 1 + app/views/configure/reading.phtml | 9 +- app/views/configure/shortcut.phtml | 7 +- app/views/configure/system.phtml | 5 +- app/views/entry/bookmark.phtml | 1 + app/views/entry/read.phtml | 1 + app/views/error/index.phtml | 5 +- app/views/extension/configure.phtml | 2 +- app/views/extension/index.phtml | 5 +- app/views/feed/add.phtml | 1 + app/views/feed/contentSelectorPreview.phtml | 7 +- app/views/helpers/category/update.phtml | 3 +- app/views/helpers/configure/query.phtml | 1 + app/views/helpers/export/articles.phtml | 1 + app/views/helpers/export/opml.phtml | 1 + app/views/helpers/extension/configure.phtml | 1 + app/views/helpers/extension/details.phtml | 1 + app/views/helpers/feed/update.phtml | 1 + app/views/helpers/index/normal/entry_bottom.phtml | 1 + app/views/helpers/index/normal/entry_header.phtml | 1 + app/views/helpers/javascript_vars.phtml | 1 + app/views/helpers/logs_pagination.phtml | 6 +- app/views/helpers/pagination.phtml | 1 + app/views/importExport/export.phtml | 1 + app/views/importExport/index.phtml | 5 +- app/views/index/about.phtml | 9 +- app/views/index/global.phtml | 1 + app/views/index/logs.phtml | 1 + app/views/index/normal.phtml | 1 + app/views/index/reader.phtml | 1 + app/views/index/rss.phtml | 1 + app/views/index/tos.phtml | 1 + app/views/javascript/actualize.phtml | 1 + app/views/javascript/nbUnreadsPerFeed.phtml | 1 + app/views/javascript/nonce.phtml | 1 + app/views/stats/idle.phtml | 5 +- app/views/stats/index.phtml | 5 +- app/views/stats/repartition.phtml | 5 +- app/views/subscription/add.phtml | 7 +- app/views/subscription/bookmarklet.phtml | 5 +- app/views/subscription/category.phtml | 2 +- app/views/subscription/feed.phtml | 1 + app/views/subscription/index.phtml | 7 +- app/views/tag/getTagsForEntry.phtml | 1 + app/views/tag/index.phtml | 7 +- app/views/update/apply.phtml | 10 +- app/views/update/checkInstall.phtml | 5 +- app/views/update/index.phtml | 5 +- app/views/user/details.phtml | 5 +- app/views/user/manage.phtml | 7 +- app/views/user/profile.phtml | 3 +- app/views/user/validateEmail.phtml | 1 + .../user_mailer/email_need_validation.txt.php | 1 + cli/_update-or-create-user.php | 6 +- cli/create-user.php | 4 +- cli/update-user.php | 4 +- cli/user-info.php | 2 +- composer.json | 5 +- composer.lock | 265 +++++++++++++-------- lib/Minz/ActionController.php | 9 +- lib/Minz/Configuration.php | 10 +- lib/Minz/ControllerNotExistException.php | 2 +- lib/Minz/Dispatcher.php | 1 - lib/Minz/Mailer.php | 4 + lib/Minz/Paginator.php | 4 +- lib/Minz/PdoMysql.php | 2 + lib/Minz/PdoSqlite.php | 2 + p/api/fever.php | 1 + p/api/greader.php | 3 +- phpstan.neon | 25 ++ 106 files changed, 662 insertions(+), 276 deletions(-) create mode 100644 app/Models/View.php create mode 100644 phpstan.neon diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9b5e9d03c..ce4c2ecc0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -46,6 +46,9 @@ jobs: - name: PHP_CodeSniffer run: composer run-script phpcs + - name: PHPStan + run: composer run-script phpstan + # NPM tests - name: Uses Node.js diff --git a/app/Controllers/authController.php b/app/Controllers/authController.php index e48bf39e8..085278a4f 100644 --- a/app/Controllers/authController.php +++ b/app/Controllers/authController.php @@ -22,7 +22,7 @@ class FreshRSS_auth_Controller extends Minz_ActionController { Minz_Error::error(403); } - Minz_View::prependTitle(_t('admin.auth.title') . ' · '); + FreshRSS_View::prependTitle(_t('admin.auth.title') . ' · '); if (Minz_Request::isPost()) { $ok = true; @@ -107,8 +107,8 @@ class FreshRSS_auth_Controller extends Minz_ActionController { public function formLoginAction() { invalidateHttpCache(); - Minz_View::prependTitle(_t('gen.auth.login') . ' · '); - Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'))); + FreshRSS_View::prependTitle(_t('gen.auth.login') . ' · '); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'))); $limits = FreshRSS_Context::$system_conf->limits; $this->view->cookie_days = round($limits['cookie_duration'] / 86400, 1); @@ -237,6 +237,6 @@ class FreshRSS_auth_Controller extends Minz_ActionController { $this->view->show_tos_checkbox = file_exists(join_path(DATA_PATH, 'tos.html')); $this->view->show_email_field = FreshRSS_Context::$system_conf->force_email_validation; $this->view->preferred_language = Minz_Translate::getLanguage(null, Minz_Request::getPreferredLanguages(), FreshRSS_Context::$system_conf->language); - Minz_View::prependTitle(_t('gen.auth.registration.title') . ' · '); + FreshRSS_View::prependTitle(_t('gen.auth.registration.title') . ' · '); } } diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index e8d8fb546..b8bf97e77 100755 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -70,7 +70,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { $this->view->themes = FreshRSS_Themes::get(); - Minz_View::prependTitle(_t('conf.display.title') . ' · '); + FreshRSS_View::prependTitle(_t('conf.display.title') . ' · '); } /** @@ -134,7 +134,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { Minz_Request::good(_t('feedback.conf.updated'), [ 'c' => 'configure', 'a' => 'reading' ]); } - Minz_View::prependTitle(_t('conf.reading.title') . ' · '); + FreshRSS_View::prependTitle(_t('conf.reading.title') . ' · '); } /** @@ -148,8 +148,8 @@ class FreshRSS_configure_Controller extends Minz_ActionController { * some unwanted behavior when the end-user was using an ad-blocker. */ public function integrationAction() { - Minz_View::appendScript(Minz_Url::display('/scripts/integration.js?' . @filemtime(PUBLIC_PATH . '/scripts/integration.js'))); - Minz_View::appendScript(Minz_Url::display('/scripts/draggable.js?' . @filemtime(PUBLIC_PATH . '/scripts/draggable.js'))); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/integration.js?' . @filemtime(PUBLIC_PATH . '/scripts/integration.js'))); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/draggable.js?' . @filemtime(PUBLIC_PATH . '/scripts/draggable.js'))); if (Minz_Request::isPost()) { $params = $_POST; @@ -160,7 +160,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { Minz_Request::good(_t('feedback.conf.updated'), [ 'c' => 'configure', 'a' => 'integration' ]); } - Minz_View::prependTitle(_t('conf.sharing.title') . ' · '); + FreshRSS_View::prependTitle(_t('conf.sharing.title') . ' · '); } /** @@ -191,7 +191,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { Minz_Request::good(_t('feedback.conf.shortcuts_updated'), array('c' => 'configure', 'a' => 'shortcut')); } - Minz_View::prependTitle(_t('conf.shortcut.title') . ' · '); + FreshRSS_View::prependTitle(_t('conf.shortcut.title') . ' · '); } /** @@ -264,7 +264,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { $this->view->size_total = $databaseDAO->size(true); } - Minz_View::prependTitle(_t('conf.archiving.title') . ' · '); + FreshRSS_View::prependTitle(_t('conf.archiving.title') . ' · '); } /** @@ -278,7 +278,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { * checking if categories and feeds are still in use. */ public function queriesAction() { - Minz_View::appendScript(Minz_Url::display('/scripts/draggable.js?' . @filemtime(PUBLIC_PATH . '/scripts/draggable.js'))); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/draggable.js?' . @filemtime(PUBLIC_PATH . '/scripts/draggable.js'))); $category_dao = FreshRSS_Factory::createCategoryDao(); $feed_dao = FreshRSS_Factory::createFeedDao(); @@ -287,6 +287,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { if (Minz_Request::isPost()) { $params = Minz_Request::param('queries', array()); + $queries = []; foreach ($params as $key => $query) { if (!$query['name']) { $query['name'] = _t('conf.query.number', $key + 1); @@ -319,7 +320,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { $this->view->queryId = $id; } - Minz_View::prependTitle(_t('conf.query.title') . ' · '); + FreshRSS_View::prependTitle(_t('conf.query.title') . ' · '); } /** @@ -370,7 +371,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { Minz_Request::good(_t('feedback.conf.updated'), [ 'c' => 'configure', 'a' => 'queries', 'params' => ['id' => $id] ]); } - Minz_View::prependTitle(_t('conf.query.title') . ' · ' . $query->getName() . ' · '); + FreshRSS_View::prependTitle(_t('conf.query.title') . ' · ' . $query->getName() . ' · '); } /** diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php index 15e4aa3fd..2f5c6594c 100755 --- a/app/Controllers/entryController.php +++ b/app/Controllers/entryController.php @@ -4,6 +4,13 @@ * Controller to handle every entry actions. */ class FreshRSS_entry_Controller extends Minz_ActionController { + + /** + * JavaScript request or not. + * @var bool + */ + private $ajax = false; + /** * This action is called before every other action in that class. It is * the common boiler plate for every action. It is triggered by the @@ -114,7 +121,7 @@ class FreshRSS_entry_Controller extends Minz_ActionController { 'c' => 'index', 'a' => 'index', 'params' => $params, - ), true); + )); } } diff --git a/app/Controllers/errorController.php b/app/Controllers/errorController.php index 325081aed..658cc71af 100644 --- a/app/Controllers/errorController.php +++ b/app/Controllers/errorController.php @@ -63,6 +63,6 @@ class FreshRSS_error_Controller extends Minz_ActionController { $this->view->errorMessage = $error_message; } - Minz_View::prependTitle($this->view->code . ' · '); + FreshRSS_View::prependTitle($this->view->code . ' · '); } } diff --git a/app/Controllers/extensionController.php b/app/Controllers/extensionController.php index a932954a9..69f52cebf 100644 --- a/app/Controllers/extensionController.php +++ b/app/Controllers/extensionController.php @@ -19,7 +19,7 @@ class FreshRSS_extension_Controller extends Minz_ActionController { * This action lists all the extensions available to the current user. */ public function indexAction() { - Minz_View::prependTitle(_t('admin.extensions.title') . ' · '); + FreshRSS_View::prependTitle(_t('admin.extensions.title') . ' · '); $this->view->extension_list = array( 'system' => array(), 'user' => array(), diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index c94b3216a..1f64687de 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -190,19 +190,19 @@ class FreshRSS_feed_Controller extends Minz_ActionController { } catch (FreshRSS_BadUrl_Exception $e) { // Given url was not a valid url! Minz_Log::warning($e->getMessage()); - Minz_Request::bad(_t('feedback.sub.feed.invalid_url', $url), $url_redirect); + return Minz_Request::bad(_t('feedback.sub.feed.invalid_url', $url), $url_redirect); } catch (FreshRSS_Feed_Exception $e) { // Something went bad (timeout, server not found, etc.) Minz_Log::warning($e->getMessage()); - Minz_Request::bad(_t('feedback.sub.feed.internal_problem', _url('index', 'logs')), $url_redirect); + return Minz_Request::bad(_t('feedback.sub.feed.internal_problem', _url('index', 'logs')), $url_redirect); } catch (Minz_FileNotExistException $e) { // Cache directory doesn't exist! Minz_Log::error($e->getMessage()); - Minz_Request::bad(_t('feedback.sub.feed.internal_problem', _url('index', 'logs')), $url_redirect); + return Minz_Request::bad(_t('feedback.sub.feed.internal_problem', _url('index', 'logs')), $url_redirect); } catch (FreshRSS_AlreadySubscribed_Exception $e) { - Minz_Request::bad(_t('feedback.sub.feed.already_subscribed', $e->feedName()), $url_redirect); + return Minz_Request::bad(_t('feedback.sub.feed.already_subscribed', $e->feedName()), $url_redirect); } catch (FreshRSS_FeedNotAdded_Exception $e) { - Minz_Request::bad(_t('feedback.sub.feed.not_added', $e->feedName()), $url_redirect); + return Minz_Request::bad(_t('feedback.sub.feed.not_added', $e->feedName()), $url_redirect); } // Entries are in DB, we redirect to feed configuration page. @@ -211,10 +211,10 @@ class FreshRSS_feed_Controller extends Minz_ActionController { Minz_Request::good(_t('feedback.sub.feed.added', $feed->name()), $url_redirect); } else { // GET request: we must ask confirmation to user before adding feed. - Minz_View::prependTitle(_t('sub.feed.title_add') . ' · '); + FreshRSS_View::prependTitle(_t('sub.feed.title_add') . ' · '); - $this->catDAO = FreshRSS_Factory::createCategoryDao(); - $this->view->categories = $this->catDAO->listCategories(false); + $catDAO = FreshRSS_Factory::createCategoryDao(); + $this->view->categories = $catDAO->listCategories(false); $this->view->feed = new FreshRSS_Feed($url); try { // We try to get more information about the feed. @@ -567,6 +567,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController { $force = Minz_Request::param('force'); $maxFeeds = (int)Minz_Request::param('maxFeeds'); $noCommit = ($_POST['noCommit'] ?? 0) == 1; + $feed = null; if ($id == -1 && !$noCommit) { //Special request only to commit & refresh DB cache $updated_feeds = 0; diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php index f3b898df4..0634bf54c 100644 --- a/app/Controllers/importExportController.php +++ b/app/Controllers/importExportController.php @@ -4,6 +4,11 @@ * Controller to handle every import and export actions. */ class FreshRSS_importExport_Controller extends Minz_ActionController { + + private $catDAO; + private $entryDAO; + private $feedDAO; + /** * This action is called before every other action in that class. It is * the common boiler plate for every action. It is triggered by the @@ -26,7 +31,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController { */ public function indexAction() { $this->view->feeds = $this->feedDAO->listFeeds(); - Minz_View::prependTitle(_t('sub.import_export.title') . ' · '); + FreshRSS_View::prependTitle(_t('sub.import_export.title') . ' · '); } private static function megabytes($size_str) { @@ -504,6 +509,8 @@ class FreshRSS_importExport_Controller extends Minz_ActionController { $website = $origin['htmlUrl']; } elseif (!empty($origin['feedUrl'])) { $website = $origin['feedUrl']; + } else { + $website = ''; } $name = empty($origin['title']) ? $website : $origin['title']; diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index ff746f4bf..eadfe252b 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -41,12 +41,12 @@ class FreshRSS_index_Controller extends Minz_ActionController { $this->view->categories = FreshRSS_Context::$categories; - $this->view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title(); + $this->view->rss_title = FreshRSS_Context::$name . ' | ' . FreshRSS_View::title(); $title = FreshRSS_Context::$name; if (FreshRSS_Context::$get_unread > 0) { $title = '(' . FreshRSS_Context::$get_unread . ') ' . $title; } - Minz_View::prependTitle($title . ' · '); + FreshRSS_View::prependTitle($title . ' · '); FreshRSS_Context::$id_max = time() . '000000'; @@ -104,8 +104,8 @@ class FreshRSS_index_Controller extends Minz_ActionController { return; } - Minz_View::appendScript(Minz_Url::display('/scripts/extra.js?' . @filemtime(PUBLIC_PATH . '/scripts/extra.js'))); - Minz_View::appendScript(Minz_Url::display('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/extra.js?' . @filemtime(PUBLIC_PATH . '/scripts/extra.js'))); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); try { $this->updateContext(); @@ -115,12 +115,12 @@ class FreshRSS_index_Controller extends Minz_ActionController { $this->view->categories = FreshRSS_Context::$categories; - $this->view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title(); + $this->view->rss_title = FreshRSS_Context::$name . ' | ' . FreshRSS_View::title(); $title = _t('index.feed.title_global'); if (FreshRSS_Context::$get_unread > 0) { $title = '(' . FreshRSS_Context::$get_unread . ') ' . $title; } - Minz_View::prependTitle($title . ' · '); + FreshRSS_View::prependTitle($title . ' · '); $this->_csp([ 'default-src' => "'self'", @@ -161,7 +161,7 @@ class FreshRSS_index_Controller extends Minz_ActionController { // No layout for RSS output. $this->view->url = PUBLIC_TO_INDEX_PATH . '/' . (empty($_SERVER['QUERY_STRING']) ? '' : '?' . $_SERVER['QUERY_STRING']); - $this->view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title(); + $this->view->rss_title = FreshRSS_Context::$name . ' | ' . FreshRSS_View::title(); $this->view->_layout(false); header('Content-Type: application/rss+xml; charset=utf-8'); } @@ -253,7 +253,7 @@ class FreshRSS_index_Controller extends Minz_ActionController { * This action displays the about page of FreshRSS. */ public function aboutAction() { - Minz_View::prependTitle(_t('index.about.title') . ' · '); + FreshRSS_View::prependTitle(_t('index.about.title') . ' · '); } /** @@ -270,7 +270,7 @@ class FreshRSS_index_Controller extends Minz_ActionController { $this->view->terms_of_service = $terms_of_service; $this->view->can_register = !max_registrations_reached(); - Minz_View::prependTitle(_t('index.tos.title') . ' · '); + FreshRSS_View::prependTitle(_t('index.tos.title') . ' · '); } /** @@ -281,7 +281,7 @@ class FreshRSS_index_Controller extends Minz_ActionController { Minz_Error::error(403); } - Minz_View::prependTitle(_t('index.log.title') . ' · '); + FreshRSS_View::prependTitle(_t('index.log.title') . ' · '); if (Minz_Request::isPost()) { FreshRSS_LogDAO::truncate(); diff --git a/app/Controllers/statsController.php b/app/Controllers/statsController.php index c9a8cdc0c..980f3532d 100644 --- a/app/Controllers/statsController.php +++ b/app/Controllers/statsController.php @@ -20,7 +20,7 @@ class FreshRSS_stats_Controller extends Minz_ActionController { 'style-src' => "'self' 'unsafe-inline'", ]); - Minz_View::prependTitle(_t('admin.stats.title') . ' · '); + FreshRSS_View::prependTitle(_t('admin.stats.title') . ' · '); } private function convertToSerie($data) { @@ -57,7 +57,7 @@ class FreshRSS_stats_Controller extends Minz_ActionController { */ public function indexAction() { $statsDAO = FreshRSS_Factory::createStatsDAO(); - Minz_View::appendScript(Minz_Url::display('/scripts/vendor/chart.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/vendor/chart.min.js'))); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/vendor/chart.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/vendor/chart.min.js'))); $this->view->repartition = $statsDAO->calculateEntryRepartition(); @@ -66,6 +66,7 @@ class FreshRSS_stats_Controller extends Minz_ActionController { $this->view->average = round(array_sum(array_values($entryCount)) / count($entryCount), 2); $feedByCategory_calculated = $statsDAO->calculateFeedByCategory(); + $feedByCategory = []; for ($i = 0; $i < count($feedByCategory_calculated); $i++) { $feedByCategory['label'][$i] = $feedByCategory_calculated[$i]['label']; $feedByCategory['data'][$i] = $feedByCategory_calculated[$i]['data']; @@ -73,6 +74,7 @@ class FreshRSS_stats_Controller extends Minz_ActionController { $this->view->feedByCategory = $feedByCategory; $entryByCategory_calculated = $statsDAO->calculateEntryByCategory(); + $entryByCategory = []; for ($i = 0; $i < count($entryByCategory_calculated); $i++) { $entryByCategory['label'][$i] = $entryByCategory_calculated[$i]['label']; $entryByCategory['data'][$i] = $entryByCategory_calculated[$i]['data']; @@ -81,6 +83,7 @@ class FreshRSS_stats_Controller extends Minz_ActionController { $this->view->topFeed = $statsDAO->calculateTopFeed(); + $last30DaysLabels = []; for ($i = 0; $i < 30; $i++) { $last30DaysLabels[$i] = date('d.m.Y', strtotime((-30 + $i) . ' days')); } @@ -178,7 +181,7 @@ class FreshRSS_stats_Controller extends Minz_ActionController { $categoryDAO = FreshRSS_Factory::createCategoryDao(); $feedDAO = FreshRSS_Factory::createFeedDao(); - Minz_View::appendScript(Minz_Url::display('/scripts/vendor/chart.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/vendor/chart.min.js'))); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/vendor/chart.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/vendor/chart.min.js'))); $id = Minz_Request::param('id', null); @@ -198,6 +201,7 @@ class FreshRSS_stats_Controller extends Minz_ActionController { $this->view->repartitionMonth = $statsDAO->calculateEntryRepartitionPerFeedPerMonth($id); $this->view->averageMonth = $statsDAO->calculateEntryAveragePerFeedPerMonth($id); + $hours24Labels = []; for ($i = 0; $i < 24; $i++) { $hours24Labels[$i] = $i . ':xx'; } diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index 5a89d0e08..c01e01843 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -44,8 +44,8 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { * It displays categories and associated feeds. */ public function indexAction() { - Minz_View::appendScript(Minz_Url::display('/scripts/category.js?' . @filemtime(PUBLIC_PATH . '/scripts/category.js'))); - Minz_View::prependTitle(_t('sub.title') . ' · '); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/category.js?' . @filemtime(PUBLIC_PATH . '/scripts/category.js'))); + FreshRSS_View::prependTitle(_t('sub.title') . ' · '); $this->view->onlyFeedsWithError = Minz_Request::paramTernary('error'); @@ -104,7 +104,7 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { $feed = $this->view->feeds[$id]; $this->view->feed = $feed; - Minz_View::prependTitle(_t('sub.title.feed_management') . ' · ' . $feed->name() . ' · '); + FreshRSS_View::prependTitle(_t('sub.title.feed_management') . ' · ' . $feed->name() . ' · '); if (Minz_Request::isPost()) { $user = trim(Minz_Request::param('http_user_feed' . $id, '')); @@ -282,13 +282,13 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { * This action displays the bookmarklet page. */ public function bookmarkletAction() { - Minz_View::prependTitle(_t('sub.title.subscription_tools') . ' . '); + FreshRSS_View::prependTitle(_t('sub.title.subscription_tools') . ' . '); } /** * This action displays the page to add a new feed */ public function addAction() { - Minz_View::prependTitle(_t('sub.title.add') . ' . '); + FreshRSS_View::prependTitle(_t('sub.title.add') . ' . '); } } diff --git a/app/Controllers/tagController.php b/app/Controllers/tagController.php index 0a57c0df2..077be9700 100644 --- a/app/Controllers/tagController.php +++ b/app/Controllers/tagController.php @@ -4,6 +4,13 @@ * Controller to handle every tag actions. */ class FreshRSS_tag_Controller extends Minz_ActionController { + + /** + * JavaScript request or not. + * @var bool + */ + private $ajax = false; + /** * This action is called before every other action in that class. It is * the common boiler plate for every action. It is triggered by the @@ -92,10 +99,10 @@ class FreshRSS_tag_Controller extends Minz_ActionController { $tagDAO = FreshRSS_Factory::createTagDao(); if (strlen($name) > 0 && null === $tagDAO->searchByName($name)) { $tagDAO->addTag(['name' => $name]); - Minz_Request::good(_t('feedback.tag.created', $name), ['c' => 'tag', 'a' => 'index'], true); + Minz_Request::good(_t('feedback.tag.created', $name), ['c' => 'tag', 'a' => 'index']); } - Minz_Request::bad(_t('feedback.tag.name_exists', $name), ['c' => 'tag', 'a' => 'index'], true); + Minz_Request::bad(_t('feedback.tag.name_exists', $name), ['c' => 'tag', 'a' => 'index']); } public function renameAction() { @@ -123,7 +130,7 @@ class FreshRSS_tag_Controller extends Minz_ActionController { $tagDAO->deleteTag($sourceId); } - Minz_Request::good(_t('feedback.tag.renamed', $sourceName, $targetName), ['c' => 'tag', 'a' => 'index'], true); + Minz_Request::good(_t('feedback.tag.renamed', $sourceName, $targetName), ['c' => 'tag', 'a' => 'index']); } public function indexAction() { diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php index 862fb0cf9..16ab7e427 100644 --- a/app/Controllers/updateController.php +++ b/app/Controllers/updateController.php @@ -108,7 +108,7 @@ class FreshRSS_update_Controller extends Minz_ActionController { } public function indexAction() { - Minz_View::prependTitle(_t('admin.update.title') . ' · '); + FreshRSS_View::prependTitle(_t('admin.update.title') . ' · '); if (file_exists(UPDATE_FILENAME)) { // There is an update file to apply! @@ -224,6 +224,7 @@ class FreshRSS_update_Controller extends Minz_ActionController { $res = !self::hasGitUpdate(); } else { require(UPDATE_FILENAME); + // @phpstan-ignore-next-line $res = do_post_update(); } @@ -244,9 +245,12 @@ class FreshRSS_update_Controller extends Minz_ActionController { } else { require(UPDATE_FILENAME); if (Minz_Request::isPost()) { + // @phpstan-ignore-next-line save_info_update(); } + // @phpstan-ignore-next-line if (!need_info_update()) { + // @phpstan-ignore-next-line $res = apply_update(); } else { return; @@ -269,7 +273,7 @@ class FreshRSS_update_Controller extends Minz_ActionController { * This action displays information about installation. */ public function checkInstallAction() { - Minz_View::prependTitle(_t('admin.check_install.title') . ' · '); + FreshRSS_View::prependTitle(_t('admin.check_install.title') . ' · '); $this->view->status_php = check_install_php(); $this->view->status_files = check_install_files(); diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php index 81f8b20a8..b1f34ce61 100644 --- a/app/Controllers/userController.php +++ b/app/Controllers/userController.php @@ -95,9 +95,9 @@ class FreshRSS_user_Controller extends Minz_ActionController { $this->view->disable_aside = true; } - Minz_View::prependTitle(_t('conf.profile.title') . ' · '); + FreshRSS_View::prependTitle(_t('conf.profile.title') . ' · '); - Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'))); + FreshRSS_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'))); if (Minz_Request::isPost()) { $system_conf = FreshRSS_Context::$system_conf; @@ -173,7 +173,7 @@ class FreshRSS_user_Controller extends Minz_ActionController { Minz_Error::error(403); } - Minz_View::prependTitle(_t('admin.user.title') . ' · '); + FreshRSS_View::prependTitle(_t('admin.user.title') . ' · '); if (Minz_Request::isPost()) { $action = Minz_Request::param('action'); @@ -227,6 +227,7 @@ class FreshRSS_user_Controller extends Minz_ActionController { $ok = self::checkUsername($new_user_name); $homeDir = join_path(DATA_PATH, 'users', $new_user_name); + $configPath = ''; if ($ok) { $languages = Minz_Translate::availableLanguages(); @@ -418,7 +419,7 @@ class FreshRSS_user_Controller extends Minz_ActionController { Minz_Error::error(404); } - Minz_View::prependTitle(_t('user.email.validation.title') . ' · '); + FreshRSS_View::prependTitle(_t('user.email.validation.title') . ' · '); $this->view->_layout('simple'); $username = Minz_Request::param('username'); @@ -429,11 +430,11 @@ class FreshRSS_user_Controller extends Minz_ActionController { } elseif (FreshRSS_Auth::hasAccess()) { $user_config = FreshRSS_Context::$user_conf; } else { - Minz_Error::error(403); + return Minz_Error::error(403); } if (!FreshRSS_UserDAO::exists($username) || $user_config === null) { - Minz_Error::error(404); + return Minz_Error::error(404); } if ($user_config->email_validation_token === '') { diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 54caef3bc..64b8d13ae 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -24,6 +24,8 @@ class FreshRSS extends Minz_FrontController { Minz_Session::init('FreshRSS'); } + Minz_ActionController::$viewType = 'FreshRSS_View'; + FreshRSS_Context::initSystem(); if (FreshRSS_Context::$system_conf == null) { $message = 'Error during context system init!'; @@ -105,7 +107,7 @@ class FreshRSS extends Minz_FrontController { case '.js': $theme_id = $theme['id']; $filename = $file; - Minz_View::prependScript(Minz_Url::display(FreshRSS::getThemeFileUrl($theme_id, $filename))); + FreshRSS_View::prependScript(Minz_Url::display(FreshRSS::getThemeFileUrl($theme_id, $filename))); break; case '.css': default: @@ -120,21 +122,21 @@ class FreshRSS extends Minz_FrontController { $filename = substr($filename, 0, -4); $filename = $filename . '.rtl.css'; } - Minz_View::prependStyle(Minz_Url::display(FreshRSS::getThemeFileUrl($theme_id, $filename))); + FreshRSS_View::prependStyle(Minz_Url::display(FreshRSS::getThemeFileUrl($theme_id, $filename))); } } } //Use prepend to insert before extensions. Added in reverse order. if (Minz_Request::controllerName() !== 'index') { - Minz_View::prependScript(Minz_Url::display('/scripts/extra.js?' . @filemtime(PUBLIC_PATH . '/scripts/extra.js'))); + FreshRSS_View::prependScript(Minz_Url::display('/scripts/extra.js?' . @filemtime(PUBLIC_PATH . '/scripts/extra.js'))); } - Minz_View::prependScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js'))); + FreshRSS_View::prependScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js'))); } private static function loadNotifications() { $notif = Minz_Request::getNotification(); if ($notif) { - Minz_View::_param('notification', $notif); + FreshRSS_View::_param('notification', $notif); } } diff --git a/app/Models/DatabaseDAO.php b/app/Models/DatabaseDAO.php index 86f72b14c..b1ce0cca6 100644 --- a/app/Models/DatabaseDAO.php +++ b/app/Models/DatabaseDAO.php @@ -24,7 +24,7 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { $db = FreshRSS_Context::$system_conf->db; try { - $sql = sprintf($SQL_CREATE_DB, empty($db['base']) ? '' : $db['base']); + $sql = sprintf($GLOBALS['SQL_CREATE_DB'], empty($db['base']) ? '' : $db['base']); return $this->pdo->exec($sql) === false ? 'Error during CREATE DATABASE' : ''; } catch (Exception $e) { syslog(LOG_DEBUG, __method__ . ' notice: ' . $e->getMessage()); @@ -176,7 +176,7 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { $ok = false; try { - $ok = $this->pdo->exec($SQL_UPDATE_GUID_LATIN1_BIN) !== false; //FreshRSS 1.12 + $ok = $this->pdo->exec($GLOBALS['SQL_UPDATE_GUID_LATIN1_BIN']) !== false; //FreshRSS 1.12 } catch (Exception $e) { $ok = false; Minz_Log::error(__METHOD__ . ' error: ' . $e->getMessage()); @@ -277,6 +277,8 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { $entryFrom = $entryDAOSQLite; $entryTo = $entryDAO; $tagFrom = $tagDAOSQLite; $tagTo = $tagDAO; break; + default: + return; } $idMaps = []; diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 7c133a2f4..7b7f5f53e 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -32,7 +32,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { try { require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); Minz_Log::warning('SQL CREATE TABLE entrytmp...'); - $ok = $this->pdo->exec($SQL_CREATE_TABLE_ENTRYTMP . $SQL_CREATE_INDEX_ENTRY_1) !== false; + $ok = $this->pdo->exec($GLOBALS['SQL_CREATE_TABLE_ENTRYTMP'] . $GLOBALS['SQL_CREATE_INDEX_ENTRY_1']) !== false; } catch (Exception $ex) { Minz_Log::error(__method__ . ' error: ' . $ex->getMessage()); } diff --git a/app/Models/Search.php b/app/Models/Search.php index 47aaa6078..08669f738 100644 --- a/app/Models/Search.php +++ b/app/Models/Search.php @@ -570,7 +570,6 @@ class FreshRSS_Search { * Supported delimiters are single quote (') and double quotes ("). * * @param string $input - * @return string */ private function parseSearch($input) { $input = self::cleanSearch($input); diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php index b5b59afd9..03ef5421b 100644 --- a/app/Models/TagDAO.php +++ b/app/Models/TagDAO.php @@ -20,7 +20,7 @@ class FreshRSS_TagDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $databaseDAO->ensureCaseInsensitiveGuids(); Minz_Log::warning('SQL CREATE TABLE tag...'); - $ok = $this->pdo->exec($SQL_CREATE_TABLE_TAGS) !== false; + $ok = $this->pdo->exec($GLOBALS['SQL_CREATE_TABLE_TAGS']) !== false; } catch (Exception $e) { Minz_Log::error('FreshRSS_EntryDAO::createTagTable error: ' . $e->getMessage()); } diff --git a/app/Models/UserDAO.php b/app/Models/UserDAO.php index 1596fa5cc..c9a3436d8 100644 --- a/app/Models/UserDAO.php +++ b/app/Models/UserDAO.php @@ -5,9 +5,10 @@ class FreshRSS_UserDAO extends Minz_ModelPdo { require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); try { - $sql = $SQL_CREATE_TABLES . $SQL_CREATE_TABLE_ENTRYTMP . $SQL_CREATE_TABLE_TAGS; + $sql = $GLOBALS['$SQL_CREATE_TABLES'] . $GLOBALS['SQL_CREATE_TABLE_ENTRYTMP'] . $GLOBALS['SQL_CREATE_TABLE_TAGS']; $ok = $this->pdo->exec($sql) !== false; //Note: Only exec() can take multiple statements safely. } catch (Exception $e) { + $ok = false; Minz_Log::error('Error while creating database for user ' . $this->current_user . ': ' . $e->getMessage()); } @@ -26,7 +27,7 @@ class FreshRSS_UserDAO extends Minz_ModelPdo { } require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); - $ok = $this->pdo->exec($SQL_DROP_TABLES) !== false; + $ok = $this->pdo->exec($GLOBALS['SQL_DROP_TABLES']) !== false; if ($ok) { return true; diff --git a/app/Models/View.php b/app/Models/View.php new file mode 100644 index 000000000..22bc2c49a --- /dev/null +++ b/app/Models/View.php @@ -0,0 +1,119 @@ +categories = $this->category_dao->listCategories(); $day = date('Y-m-d'); @@ -108,7 +108,7 @@ class FreshRSS_Export_Service { return null; } - $view = new Minz_View(); + $view = new FreshRSS_View(); $view->categories = $this->category_dao->listCategories(); $view->feed = $feed; $day = date('Y-m-d'); diff --git a/app/actualize_script.php b/app/actualize_script.php index 1e3514de7..721376f62 100755 --- a/app/actualize_script.php +++ b/app/actualize_script.php @@ -2,20 +2,6 @@ auth_type = 'none'; // avoid necessity to be logged in (not saved!) define('SIMPLEPIE_SYSLOG_ENABLED', FreshRSS_Context::$system_conf->simplepie_syslog_enabled); +/** + * Writes to FreshRSS admin log, and if it is not already done by default, + * writes to syslog (only if simplepie_syslog_enabled in FreshRSS configuration) and to STDOUT + */ +function notice($message) { + Minz_Log::notice($message, ADMIN_LOG); + if (!COPY_LOG_TO_SYSLOG && SIMPLEPIE_SYSLOG_ENABLED) { + syslog(LOG_NOTICE, $message); + } + if (defined('STDOUT') && !COPY_SYSLOG_TO_STDERR) { + fwrite(STDOUT, $message . "\n"); //Unbuffered + } +} + 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 diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml index 63dc28bd1..747f4e05f 100644 --- a/app/layout/aside_feed.phtml +++ b/app/layout/aside_feed.phtml @@ -1,4 +1,5 @@ hide_read_feeds && diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index 5cf3e3ae0..cb9b6c1ba 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -1,4 +1,7 @@ - + - + - + @@ -25,7 +28,7 @@ if (_t('gen.dir') === 'rtl') { allow_referrer) { ?> - + rss_title)) { diff --git a/app/layout/simple.phtml b/app/layout/simple.phtml index 4357b6fdf..1858c3fed 100644 --- a/app/layout/simple.phtml +++ b/app/layout/simple.phtml @@ -1,14 +1,17 @@ - + - + - + @@ -18,7 +21,7 @@ - + diff --git a/app/views/auth/formLogin.phtml b/app/views/auth/formLogin.phtml index e61aaf922..e218d089d 100644 --- a/app/views/auth/formLogin.phtml +++ b/app/views/auth/formLogin.phtml @@ -1,3 +1,4 @@ +

diff --git a/app/views/auth/index.phtml b/app/views/auth/index.phtml index 9c9cd1eaa..a18ab49e2 100644 --- a/app/views/auth/index.phtml +++ b/app/views/auth/index.phtml @@ -1,4 +1,7 @@ -partial('aside_configure'); ?> +partial('aside_configure'); +?>