PHPStan Level 7 for ten more files (#5327)

* PHPStan Level 7 for nine more files

* Minor syntax

* One more
This commit is contained in:
Alexandre Alapetite
2023-04-23 11:58:15 +02:00
committed by GitHub
parent 8abe53d879
commit 115724622f
19 changed files with 58 additions and 67 deletions

View File

@@ -244,9 +244,9 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController {
/**
* This method returns a list of entries based on the Context object.
* @return iterable<FreshRSS_Entry>
* @return Traversable<FreshRSS_Entry>
*/
public static function listEntriesByContext(): iterable {
public static function listEntriesByContext(): Traversable {
$entryDAO = FreshRSS_Factory::createEntryDao();
$get = FreshRSS_Context::currentGet(true);

View File

@@ -214,8 +214,8 @@ SQL;
}
}
/** @return iterable<array<string,string|int>> */
public function selectAll(): iterable {
/** @return Traversable<array<string,string|int>> */
public function selectAll(): Traversable {
$sql = 'SELECT id, name, kind, `lastUpdate`, error, attributes FROM `_category`';
$stm = $this->pdo->query($sql);
if ($stm != false) {

View File

@@ -220,8 +220,8 @@ HTML;
return $content;
}
/** @return iterable<array{'url':string,'type'?:string,'medium'?:string,'length'?:int,'title'?:string,'description'?:string,'credit'?:string,'height'?:int,'width'?:int,'thumbnails'?:array<string>}> */
public function enclosures(bool $searchBodyImages = false): iterable {
/** @return Traversable<array{'url':string,'type'?:string,'medium'?:string,'length'?:int,'title'?:string,'description'?:string,'credit'?:string,'height'?:int,'width'?:int,'thumbnails'?:array<string>}> */
public function enclosures(bool $searchBodyImages = false): Traversable {
$attributeEnclosures = $this->attributes('enclosures');
if (is_array($attributeEnclosures)) {
// FreshRSS 1.20.1+: The enclosures are saved as attributes

View File

@@ -696,8 +696,8 @@ SQL;
}
}
/** @return iterable<array<string,string|int>> */
public function selectAll(): iterable {
/** @return Traversable<array<string,string|int>> */
public function selectAll(): Traversable {
$sql = 'SELECT id, guid, title, author, '
. (static::isCompressed() ? 'UNCOMPRESS(content_bin) AS content' : 'content')
. ', link, date, `lastSeen`, ' . static::sqlHexEncode('hash') . ' AS hash, is_read, is_favorite, id_feed, tags, attributes '
@@ -1149,11 +1149,11 @@ SQL;
/**
* @param int $id category/feed/tag ID
* @return iterable<FreshRSS_Entry>
* @return Traversable<FreshRSS_Entry>
*/
public function listWhere(string $type = 'a', int $id = 0, int $state = FreshRSS_Entry::STATE_ALL,
string $order = 'DESC', int $limit = 1, string $firstId = '',
?FreshRSS_BooleanSearch $filters = null, int $date_min = 0): iterable {
?FreshRSS_BooleanSearch $filters = null, int $date_min = 0): Traversable {
$stm = $this->listWhereRaw($type, $id, $state, $order, $limit, $firstId, $filters, $date_min);
if ($stm) {
while ($row = $stm->fetch(PDO::FETCH_ASSOC)) {
@@ -1164,9 +1164,9 @@ SQL;
/**
* @param array<string> $ids
* @return iterable<FreshRSS_Entry>
* @return Traversable<FreshRSS_Entry>
*/
public function listByIds(array $ids, string $order = 'DESC'): iterable {
public function listByIds(array $ids, string $order = 'DESC'): Traversable {
if (count($ids) < 1) {
return;
}

View File

@@ -480,8 +480,8 @@ class FreshRSS_Feed extends Minz_Model {
return $hasUniqueGuids ? $guids : $links;
}
/** @return iterable<FreshRSS_Entry> */
public function loadEntries(SimplePie $simplePie): iterable {
/** @return Traversable<FreshRSS_Entry> */
public function loadEntries(SimplePie $simplePie): Traversable {
$hasBadGuids = $this->attributes('hasBadGuids');
$items = $simplePie->get_items();

View File

@@ -286,8 +286,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
}
}
/** @return iterable<array<string,string|int>> */
public function selectAll(): iterable {
/** @return Traversable<array<string,string|int>> */
public function selectAll(): Traversable {
$sql = <<<'SQL'
SELECT id, url, kind, category, name, website, description, `lastUpdate`,
priority, `pathEntries`, `httpAuth`, error, ttl, attributes
@@ -321,7 +321,7 @@ SQL;
return $feed == false ? null : $feed;
}
/** @return array<string>|false */
/** @return array<int>|false */
public function listFeedsIds() {
$sql = 'SELECT id FROM `_feed`';
$stm = $this->pdo->query($sql);

View File

@@ -17,9 +17,7 @@ class FreshRSS_ReadingMode {
* @var string
*/
protected $title;
/**
* @var string[]
*/
/** @var array{'c':string,'a':string,'params':array<string,mixed>} */
protected $urlParams;
/**
* @var bool
@@ -28,7 +26,7 @@ class FreshRSS_ReadingMode {
/**
* ReadingMode constructor.
* @param array<string> $urlParams
* @param array{'c':string,'a':string,'params':array<string,mixed>} $urlParams
*/
public function __construct(string $id, string $title, array $urlParams, bool $active) {
$this->id = $id;
@@ -60,16 +58,12 @@ class FreshRSS_ReadingMode {
return $this;
}
/**
* @return array<string>
*/
/** @return array{'c':string,'a':string,'params':array<string,mixed>} */
public function getUrlParams(): array {
return $this->urlParams;
}
/**
* @param array<string> $urlParams
*/
/** @param array{'c':string,'a':string,'params':array<string,mixed>} $urlParams */
public function setUrlParams(array $urlParams): FreshRSS_ReadingMode {
$this->urlParams = $urlParams;
return $this;

View File

@@ -153,8 +153,8 @@ SQL;
}
}
/** @return iterable<array{'id':int,'name':string,'attributes':string}> */
public function selectAll(): iterable {
/** @return Traversable<array{'id':int,'name':string,'attributes':string}> */
public function selectAll(): Traversable {
$sql = 'SELECT id, name, attributes FROM `_tag`';
$stm = $this->pdo->query($sql);
while ($row = $stm->fetch(PDO::FETCH_ASSOC)) {
@@ -162,8 +162,8 @@ SQL;
}
}
/** @return iterable<array{'id_tag':int,'id_entry':string}> */
public function selectEntryTag(): iterable {
/** @return Traversable<array{'id_tag':int,'id_entry':string}> */
public function selectEntryTag(): Traversable {
$sql = 'SELECT id_tag, id_entry FROM `_entrytag`';
$stm = $this->pdo->query($sql);
while ($row = $stm->fetch(PDO::FETCH_ASSOC)) {

View File

@@ -11,7 +11,7 @@ class FreshRSS_Themes extends Minz_Model {
/** @return array<string> */
public static function getList(): array {
return array_values(array_diff(
scandir(PUBLIC_PATH . self::$themesUrl),
scandir(PUBLIC_PATH . self::$themesUrl) ?: [],
array('..', '.')
));
}
@@ -37,7 +37,7 @@ class FreshRSS_Themes extends Minz_Model {
if (is_dir($theme_dir)) {
$json_filename = $theme_dir . '/metadata.json';
if (file_exists($json_filename)) {
$content = file_get_contents($json_filename);
$content = file_get_contents($json_filename) ?: '';
$res = json_decode($content, true);
if ($res &&
!empty($res['name']) &&
@@ -75,7 +75,7 @@ class FreshRSS_Themes extends Minz_Model {
}
self::$themeIconsUrl = self::$themesUrl . $theme_id . '/icons/';
self::$themeIcons = is_dir(PUBLIC_PATH . self::$themeIconsUrl) ? array_fill_keys(array_diff(
scandir(PUBLIC_PATH . self::$themeIconsUrl),
scandir(PUBLIC_PATH . self::$themeIconsUrl) ?: [],
array('..', '.')
), 1) : array();
return $infos;

View File

@@ -15,7 +15,7 @@ class FreshRSS_View extends Minz_View {
public $category;
/** @var string */
public $current_user;
/** @var array<FreshRSS_Entry> */
/** @var iterable<FreshRSS_Entry> */
public $entries;
/** @var FreshRSS_Entry */
public $entry;
@@ -49,7 +49,7 @@ class FreshRSS_View extends Minz_View {
public $signalError;
// Manage users
/** @var array<string,string|int|bool> */
/** @var array{'feed_count':int|false,'article_count':int|false,'database_size':int,'language':string,'mail_login':string,'enabled':bool,'is_admin':bool,'last_user_activity':string,'is_default':bool} */
public $details;
/** @var bool */
public $disable_aside;

View File

@@ -43,7 +43,7 @@ class FreshRSS_Export_Service {
public function generateOpml(): array {
$view = new FreshRSS_View();
$day = date('Y-m-d');
$view->categories = $this->category_dao->listCategories(true, true);
$view->categories = $this->category_dao->listCategories(true, true) ?: [];
$view->excludeMutedFeeds = false;
return [
@@ -67,7 +67,7 @@ class FreshRSS_Export_Service {
*/
public function generateStarredEntries(string $type): array {
$view = new FreshRSS_View();
$view->categories = $this->category_dao->listCategories(true);
$view->categories = $this->category_dao->listCategories(true) ?: [];
$day = date('Y-m-d');
$view->list_title = _t('sub.import_export.starred_list');
@@ -99,7 +99,7 @@ class FreshRSS_Export_Service {
}
$view = new FreshRSS_View();
$view->categories = $this->category_dao->listCategories(true);
$view->categories = $this->category_dao->listCategories(true) ?: [];
$view->feed = $feed;
$day = date('Y-m-d');
$filename = "feed_{$day}_" . $feed->categoryId() . '_' . $feed->id() . '.json';
@@ -127,7 +127,7 @@ class FreshRSS_Export_Service {
* @return array<string,string> Keys are filenames and values are contents.
*/
public function generateAllFeedEntries(int $max_number_entries): array {
$feed_ids = $this->feed_dao->listFeedsIds();
$feed_ids = $this->feed_dao->listFeedsIds() ?: [];
$exported_files = [];
foreach ($feed_ids as $feed_id) {
@@ -154,6 +154,9 @@ class FreshRSS_Export_Service {
// From https://stackoverflow.com/questions/1061710/php-zip-files-on-the-fly
$zip_file = tempnam('/tmp', 'zip');
if ($zip_file == false) {
return [$zip_filename, false];
}
$zip_archive = new ZipArchive();
$zip_archive->open($zip_file, ZipArchive::OVERWRITE);

View File

@@ -56,7 +56,7 @@ class FreshRSS_Import_Service {
// Get the categories by names so we can use this array to retrieve
// existing categories later.
$categories = $this->catDAO->listCategories(false);
$categories = $this->catDAO->listCategories(false) ?: [];
$categories_by_names = [];
foreach ($categories as $category) {
$categories_by_names[$category->name()] = $category;
@@ -180,7 +180,7 @@ class FreshRSS_Import_Service {
if (isset($feed_elt['frss:filtersActionRead'])) {
$feed->_filtersAction(
'read',
preg_split('/[\n\r]+/', $feed_elt['frss:filtersActionRead'])
preg_split('/[\n\r]+/', $feed_elt['frss:filtersActionRead']) ?: []
);
}

View File

@@ -53,6 +53,7 @@ $MAX_TAGS_DISPLAYED = FreshRSS_Context::$user_conf->show_tags_max;
<?php
$feed = FreshRSS_CategoryDAO::findFeed($this->categories, $item->feedId()); //We most likely already have the feed object in cache
if ($feed == null) $feed = $item->feed();
if ($feed == null) continue;
$favoriteUrl = array('c' => 'entry', 'a' => 'bookmark', 'params' => array('id' => $item->id()));
if ($item->isFavorite()) {
$favoriteUrl['params']['is_favorite'] = 0;

View File

@@ -28,14 +28,14 @@
<div class="form-group">
<label class="group-name"><?= _t('admin.user.feed_count') ?></label>
<div class="group-controls">
<?= format_number($this->details['feed_count']) ?>
<?= format_number($this->details['feed_count'] ?: 0) ?>
</div>
</div>
<div class="form-group">
<label class="group-name"><?= _t('admin.user.article_count') ?></label>
<div class="group-controls">
<?= format_number($this->details['article_count']) ?>
<?= format_number($this->details['article_count'] ?: 0) ?>
</div>
</div>

View File

@@ -31,7 +31,7 @@ $dBparams = array(
$options = getopt('', array_merge($params, $dBparams));
if (!validateOptions($argv, array_merge($params, $dBparams)) || empty($options['default_user'])) {
if (!validateOptions($argv, array_merge($params, $dBparams)) || empty($options['default_user']) || !is_string($options['default_user'])) {
fail('Usage: ' . basename(__FILE__) . " --default_user admin ( --auth_type form" .
" --environment production --base_url https://rss.example.net --allow_robots" .
" --language en --title FreshRSS --allow_anonymous --allow_anonymous_refresh --api_enabled" .
@@ -81,8 +81,7 @@ if (!FreshRSS_user_Controller::checkUsername($options['default_user'])) {
}
if (isset($options['auth_type']) && !in_array($options['auth_type'], array('form', 'http_auth', 'none'))) {
fail('FreshRSS invalid authentication method (auth_type must be one of { form, http_auth, none }): '
. $options['auth_type']);
fail('FreshRSS invalid authentication method (auth_type must be one of { form, http_auth, none })');
}
if (file_put_contents(join_path(DATA_PATH, 'config.php'),

View File

@@ -4,7 +4,7 @@ require_once __DIR__ . '/I18nValue.php';
class I18nFile {
/**
* @return array<string,array<string,string|array<string,I18nValue>>>
* @return array<string,array<string,array<string,I18nValue>>>
*/
public function load(): array {
$i18n = array();

View File

@@ -284,7 +284,7 @@ final class GReaderAPI {
);
$categoryDAO = FreshRSS_Factory::createCategoryDao();
$categories = $categoryDAO->listCategories(true, false);
$categories = $categoryDAO->listCategories(true, false) ?: [];
foreach ($categories as $cat) {
$tags[] = array(
'id' => 'user/-/label/' . htmlspecialchars_decode($cat->name(), ENT_QUOTES),
@@ -294,7 +294,7 @@ final class GReaderAPI {
}
$tagDAO = FreshRSS_Factory::createTagDao();
$labels = $tagDAO->listTags(true);
$labels = $tagDAO->listTags(true) ?: [];
foreach ($labels as $label) {
$tags[] = array(
'id' => 'user/-/label/' . htmlspecialchars_decode($label->name(), ENT_QUOTES),
@@ -345,7 +345,7 @@ final class GReaderAPI {
$subscriptions = array();
$categoryDAO = FreshRSS_Factory::createCategoryDao();
foreach ($categoryDAO->listCategories(true, true) as $cat) {
foreach ($categoryDAO->listCategories(true, true) ?: [] as $cat) {
foreach ($cat->feeds() as $feed) {
$subscriptions[] = [
'id' => 'feed/' . $feed->id(),
@@ -418,7 +418,7 @@ final class GReaderAPI {
if ($action === 'subscribe') {
continue;
}
$feedId = $streamUrl;
$feedId = (int)$streamUrl;
} else {
$streamUrl = htmlspecialchars($streamUrl, ENT_COMPAT, 'UTF-8');
$feed = $feedDAO->searchByUrl($streamUrl);
@@ -497,7 +497,7 @@ final class GReaderAPI {
$feedDAO = FreshRSS_Factory::createFeedDao();
$feedsNewestItemUsec = $feedDAO->listFeedsNewestItemUsec();
foreach ($categoryDAO->listCategories(true, true) as $cat) {
foreach ($categoryDAO->listCategories(true, true) ?: [] as $cat) {
$catLastUpdate = 0;
foreach ($cat->feeds() as $feed) {
$lastUpdate = $feedsNewestItemUsec['f_' . $feed->id()] ?? 0;
@@ -523,7 +523,7 @@ final class GReaderAPI {
$tagDAO = FreshRSS_Factory::createTagDao();
$tagsNewestItemUsec = $tagDAO->listTagsNewestItemUsec();
foreach ($tagDAO->listTags(true) as $label) {
foreach ($tagDAO->listTags(true) ?: [] as $label) {
$lastUpdate = $tagsNewestItemUsec['t_' . $label->id()] ?? 0;
$unreadcounts[] = array(
'id' => 'user/-/label/' . htmlspecialchars_decode($label->name(), ENT_QUOTES),
@@ -554,7 +554,7 @@ final class GReaderAPI {
return array();
}
$catDAO = FreshRSS_Factory::createCategoryDao();
$categories = $catDAO->listCategories(true);
$categories = $catDAO->listCategories(true) ?: [];
$tagDAO = FreshRSS_Factory::createTagDao();
$entryIdsTagNames = $tagDAO->getEntryIdsTagNames($entries);
@@ -568,6 +568,9 @@ final class GReaderAPI {
}
$feed = FreshRSS_CategoryDAO::findFeed($categories, $entry->feedId());
if ($feed === null) {
continue;
}
$entry->_feed($feed);
if (isset($entryIdsTagNames['e_' . $entry->id()])) {
@@ -580,8 +583,9 @@ final class GReaderAPI {
}
/**
* @param 'A'|'c'|'f'|'s' $type
* @param string|int $streamId
* @return array{string,int,int,FreshRSS_BooleanSearch}
* @return array{'A'|'c'|'f'|'s'|'t',int,int,FreshRSS_BooleanSearch}
*/
private static function streamContentsFilters(string $type, $streamId,
string $filter_target, string $exclude_target, int $start_time, int $stop_time): array {

View File

@@ -15,7 +15,7 @@ class I18nFileTest extends PHPUnit\Framework\TestCase {
$this->assertEquals($before, $after);
}
/** @return array<string,string> */
/** @return array<string,string|false> */
private function computeFilesHash(): array {
$hashes = [];

View File

@@ -16,27 +16,17 @@
./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/Services/ExportService.php
./app/Services/ImportService.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
./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