Skip to content

Commit

Permalink
Pass PHPStan level 9 (FreshRSS#6544)
Browse files Browse the repository at this point in the history
* More PHPStan

* More, passing

* 4 more files

* Update to PHPStan 1.11.4
Needed for fixed bug: Consider numeric-string types after string concat
https://github.com/phpstan/phpstan/releases/tag/1.11.4

* Pass PHPStan level 9
Start tracking booleansInConditions

* Fix mark as read

* Fix doctype

* ctype_digit
  • Loading branch information
Alkarex authored Jun 9, 2024
1 parent e98c578 commit 5b28a35
Show file tree
Hide file tree
Showing 38 changed files with 250 additions and 184 deletions.
4 changes: 2 additions & 2 deletions app/Controllers/apiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static function updatePassword(string $apiPasswordPlain) {
FreshRSS_Context::userConf()->apiPasswordHash = $apiPasswordHash;

$feverKey = FreshRSS_fever_Util::updateKey($username, $apiPasswordPlain);
if (!$feverKey) {
if ($feverKey == false) {
return _t('feedback.api.password.failed');
}

Expand Down Expand Up @@ -56,7 +56,7 @@ public function updatePasswordAction(): void {
}

$error = self::updatePassword($apiPasswordPlain);
if ($error) {
if (is_string($error)) {
Minz_Request::bad($error, $return_url);
} else {
Minz_Request::good(_t('feedback.api.password.updated'), $return_url);
Expand Down
2 changes: 1 addition & 1 deletion app/Controllers/authController.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public function formLoginAction(): void {
$password = Minz_Request::paramString('p');
Minz_Request::_param('p');

if (!$username) {
if ($username === '') {
return;
}

Expand Down
19 changes: 10 additions & 9 deletions app/Controllers/configureController.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ public function shortcutAction(): void {
$default = Minz_Configuration::load(FRESHRSS_PATH . '/config-user.default.php');
$shortcuts = $default['shortcuts'];
}
/** @var array<string,string> $shortcuts */
FreshRSS_Context::userConf()->shortcuts = array_map('trim', $shortcuts);
FreshRSS_Context::userConf()->save();
invalidateHttpCache();
Expand Down Expand Up @@ -384,27 +385,27 @@ public function queryAction(): void {
$queryParams['search'] = htmlspecialchars_decode($params['search'], ENT_QUOTES);
}
if (!empty($params['state']) && is_array($params['state'])) {
$queryParams['state'] = (int)(array_sum($params['state']));
$queryParams['state'] = (int)array_sum($params['state']);
}
if (empty($params['token']) || !is_string($params['token'])) {
$queryParams['token'] = FreshRSS_UserQuery::generateToken($name);
} else {
$queryParams['token'] = $params['token'];
}
if (!empty($params['shareRss']) && ctype_digit($params['shareRss'])) {
$queryParams['shareRss'] = (bool)$params['shareRss'];
}
if (!empty($params['shareOpml']) && ctype_digit($params['shareOpml'])) {
$queryParams['shareOpml'] = (bool)$params['shareOpml'];
}
$queryParams['url'] = Minz_Url::display(['params' => $queryParams]);
$queryParams['name'] = $name;
if (!empty($params['description']) && is_string($params['description'])) {
$queryParams['description'] = htmlspecialchars_decode($params['description'], ENT_QUOTES);
}
if (!empty($params['imageUrl']) && is_string($params['imageUrl'])) {
$queryParams['imageUrl'] = $params['imageUrl'];
}
$queryParams['url'] = Minz_Url::display(['params' => $queryParams]);
$queryParams['name'] = $name;
if (!empty($params['shareOpml']) && ctype_digit($params['shareOpml'])) {
$queryParams['shareOpml'] = (bool)$params['shareOpml'];
}
if (!empty($params['shareRss']) && ctype_digit($params['shareRss'])) {
$queryParams['shareRss'] = (bool)$params['shareRss'];
}

$queries = FreshRSS_Context::userConf()->queries;
$queries[$id] = (new FreshRSS_UserQuery($queryParams, FreshRSS_Context::categories(), FreshRSS_Context::labels()))->toArray();
Expand Down
23 changes: 17 additions & 6 deletions app/Controllers/entryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ public function firstAction(): void {
* - is_read (default: true)
*/
public function readAction(): void {
$id = Minz_Request::param('id');
$get = Minz_Request::paramString('get');
$next_get = Minz_Request::paramString('nextGet') ?: $get;
$id_max = Minz_Request::paramString('idMax') ?: '0';
if (!ctype_digit($id_max)) {
$id_max = '0';
}
$is_read = Minz_Request::paramTernary('is_read') ?? true;
FreshRSS_Context::$search = new FreshRSS_BooleanSearch(Minz_Request::paramString('search'));

Expand All @@ -64,14 +66,14 @@ public function readAction(): void {
$this->view->tagsForEntries = [];

$entryDAO = FreshRSS_Factory::createEntryDao();
if ($id == false) {
// id is false? It MUST be a POST request!
if (!Minz_Request::hasParam('id')) {
// No id, then it MUST be a POST request
if (!Minz_Request::isPost()) {
Minz_Request::bad(_t('feedback.access.not_found'), ['c' => 'index', 'a' => 'index']);
return;
}

if (!$get) {
if ($get === '') {
// No get? Mark all entries as read (from $id_max)
$entryDAO->markReadEntries($id_max, false, FreshRSS_Feed::PRIORITY_MAIN_STREAM, FreshRSS_Feed::PRIORITY_IMPORTANT, null, 0, $is_read);
} else {
Expand Down Expand Up @@ -111,7 +113,16 @@ public function readAction(): void {
}
}
} else {
$ids = is_array($id) ? $id : [$id];
/** @var array<numeric-string> $idArray */
$idArray = Minz_Request::paramArray('id');
$idString = Minz_Request::paramString('id');
if (count($idArray) > 0) {
$ids = $idArray;
} elseif (ctype_digit($idString)) {
$ids = [$idString];
} else {
$ids = [];
}
$entryDAO->markRead($ids, $is_read);
$tagDAO = FreshRSS_Factory::createTagDao();
$tagsForEntries = $tagDAO->getTagsForEntries($ids) ?: [];
Expand Down Expand Up @@ -145,7 +156,7 @@ public function readAction(): void {
public function bookmarkAction(): void {
$id = Minz_Request::paramString('id');
$is_favourite = Minz_Request::paramTernary('is_favorite') ?? true;
if ($id != '') {
if ($id != '' && ctype_digit($id)) {
$entryDAO = FreshRSS_Factory::createEntryDao();
$entryDAO->markFavorite($id, $is_favourite);
}
Expand Down
3 changes: 1 addition & 2 deletions app/Controllers/feedController.php
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,8 @@ public static function actualizeFeeds(?int $feed_id = null, ?string $feed_url =
$nb_new_articles = 0;

foreach ($feeds as $feed) {
/** @var FreshRSS_Feed|null $feed */
$feed = Minz_ExtensionManager::callHook('feed_before_actualize', $feed);
if (null === $feed) {
if (!($feed instanceof FreshRSS_Feed)) {
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion app/Controllers/importExportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ private function addFeedJson(array $origin): ?FreshRSS_Feed {

// Call the extension hook
$feed = Minz_ExtensionManager::callHook('feed_before_insert', $feed);
if ($feed != null) {
if ($feed instanceof FreshRSS_Feed) {
// addFeedObject checks if feed is already in DB so nothing else to
// check here.
$id = $this->feedDAO->addFeedObject($feed);
Expand Down
6 changes: 3 additions & 3 deletions app/Models/DatabaseDAO.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function tablesAreCorrect(): bool {
return count(array_keys($tables, true, true)) === count($tables);
}

/** @return array<array<string,string|int|bool|null>> */
/** @return array<array{name:string,type:string,notnull:bool,default:mixed}> */
public function getSchema(string $table): array {
$res = $this->fetchAssoc('DESC `_' . $table . '`');
return $res == null ? [] : $this->listDaoToSchema($res);
Expand Down Expand Up @@ -160,7 +160,7 @@ public function entrytagIsCorrect(): bool {

/**
* @param array<string,string|int|bool|null> $dao
* @return array{'name':string,'type':string,'notnull':bool,'default':mixed}
* @return array{name:string,type:string,notnull:bool,default:mixed}
*/
public function daoToSchema(array $dao): array {
return [
Expand All @@ -173,7 +173,7 @@ public function daoToSchema(array $dao): array {

/**
* @param array<array<string,string|int|bool|null>> $listDAO
* @return array<array<string,string|int|bool|null>>
* @return array<array{name:string,type:string,notnull:bool,default:mixed}>
*/
public function listDaoToSchema(array $listDAO): array {
$list = [];
Expand Down
2 changes: 1 addition & 1 deletion app/Models/DatabaseDAOPGSQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function tablesAreCorrect(): bool {
return count(array_keys($tables, true, true)) === count($tables);
}

/** @return array<array<string,string|int|bool|null>> */
/** @return array<array{name:string,type:string,notnull:bool,default:mixed}> */
#[\Override]
public function getSchema(string $table): array {
$sql = <<<'SQL'
Expand Down
2 changes: 1 addition & 1 deletion app/Models/DatabaseDAOSQLite.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function tablesAreCorrect(): bool {
return count(array_keys($tables, true, true)) == count($tables);
}

/** @return array<array<string,string|int|bool|null>> */
/** @return array<array{name:string,type:string,notnull:bool,default:mixed}> */
#[\Override]
public function getSchema(string $table): array {
$sql = 'PRAGMA table_info(' . $table . ')';
Expand Down
22 changes: 15 additions & 7 deletions app/Models/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class FreshRSS_Entry extends Minz_Model {
public const STATE_FAVORITE = 4;
public const STATE_NOT_FAVORITE = 8;

/** @var numeric-string */
private string $id = '0';
private string $guid;
private string $title;
Expand Down Expand Up @@ -110,6 +111,7 @@ public static function fromTraversable(Traversable $daos): Traversable {
}
}

/** @return numeric-string */
public function id(): string {
return $this->id;
}
Expand Down Expand Up @@ -195,8 +197,8 @@ public function content(bool $withEnclosures = true, bool $allowDuplicateEnclosu
$thumbnailAttribute = $this->attributeArray('thumbnail') ?? [];
if (!empty($thumbnailAttribute['url'])) {
$elink = $thumbnailAttribute['url'];
if ($allowDuplicateEnclosures || !self::containsLink($content, $elink)) {
$content .= <<<HTML
if (is_string($elink) && ($allowDuplicateEnclosures || !self::containsLink($content, $elink))) {
$content .= <<<HTML
<figure class="enclosure">
<p class="enclosure-content">
<img class="enclosure-thumbnail" src="{$elink}" alt="" />
Expand All @@ -216,7 +218,7 @@ public function content(bool $withEnclosures = true, bool $allowDuplicateEnclosu
continue;
}
$elink = $enclosure['url'] ?? '';
if ($elink == '') {
if ($elink == '' || !is_string($elink)) {
continue;
}
if (!$allowDuplicateEnclosures && self::containsLink($content, $elink)) {
Expand Down Expand Up @@ -281,6 +283,7 @@ public function enclosures(bool $searchBodyImages = false): Traversable {
$attributeEnclosures = $this->attributeArray('enclosures');
if (is_iterable($attributeEnclosures)) {
// FreshRSS 1.20.1+: The enclosures are saved as attributes
/** @var iterable<array{'url':string,'type'?:string,'medium'?:string,'length'?:int,'title'?:string,'description'?:string,'credit'?:string|array<string>,'height'?:int,'width'?:int,'thumbnails'?:array<string>}> $attributeEnclosures */
yield from $attributeEnclosures;
}
try {
Expand All @@ -296,8 +299,10 @@ public function enclosures(bool $searchBodyImages = false): Traversable {
// Legacy code for database entries < FreshRSS 1.20.1
$enclosures = $xpath->query('//div[@class="enclosure"]/p[@class="enclosure-content"]/*[@src]');
if (!empty($enclosures)) {
/** @var DOMElement $enclosure */
foreach ($enclosures as $enclosure) {
if (!($enclosure instanceof DOMElement)) {
continue;
}
$result = [
'url' => $enclosure->getAttribute('src'),
'type' => $enclosure->getAttribute('data-type'),
Expand All @@ -318,8 +323,10 @@ public function enclosures(bool $searchBodyImages = false): Traversable {
if ($searchBodyImages && $xpath !== null) {
$images = $xpath->query('//img');
if (!empty($images)) {
/** @var DOMElement $img */
foreach ($images as $img) {
if (!($img instanceof DOMElement)) {
continue;
}
$src = $img->getAttribute('src');
if ($src == null) {
$src = $img->getAttribute('data-src');
Expand All @@ -346,6 +353,7 @@ public function thumbnail(bool $searchEnclosures = true): ?array {
$thumbnail = $this->attributeArray('thumbnail') ?? [];
// First, use the provided thumbnail, if any
if (!empty($thumbnail['url'])) {
/** @var array{'url':string,'height'?:int,'width'?:int,'time'?:string} $thumbnail */
return $thumbnail;
}
if ($searchEnclosures) {
Expand Down Expand Up @@ -467,7 +475,7 @@ public function _hash(string $value): string {
return $this->hash;
}

/** @param int|string $value String is for compatibility with 32-bit platforms */
/** @param int|numeric-string $value String is for compatibility with 32-bit platforms */
public function _id($value): void {
if (is_int($value)) {
$value = (string)$value;
Expand Down Expand Up @@ -882,7 +890,7 @@ public function tagsFormattingHelper(): array {

/**
* Integer format conversion for Google Reader API format
* @param string|int $dec Decimal number
* @param numeric-string|int $dec Decimal number
* @return string 64-bit hexa http://code.google.com/p/google-reader-api/wiki/ItemId
*/
private static function dec2hex($dec): string {
Expand Down
14 changes: 7 additions & 7 deletions app/Models/EntryDAO.php
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ public function newUnreadEntriesPerFeed(): array {
* @todo simplify the query by removing the str_repeat. I am pretty sure
* there is an other way to do that.
*
* @param string|array<string> $ids
* @param numeric-string|array<numeric-string> $ids
* @return int|false
*/
public function markFavorite($ids, bool $is_favorite = true) {
Expand Down Expand Up @@ -399,7 +399,7 @@ protected function updateCacheUnreads(?int $catId = null, ?int $feedId = null):
* Toggle the read marker on one or more article.
* Then the cache is updated.
*
* @param string|array<string> $ids
* @param numeric-string|array<numeric-string> $ids
* @param bool $is_read
* @return int|false affected rows
*/
Expand Down Expand Up @@ -465,7 +465,7 @@ public function markRead($ids, bool $is_read = true) {
*
* If $idMax equals 0, a deprecated debug message is logged
*
* @param string $idMax fail safe article ID
* @param numeric-string $idMax fail safe article ID
* @return int|false affected rows
*/
public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false, ?int $priorityMin = null, ?int $prioritMax = null,
Expand Down Expand Up @@ -517,7 +517,7 @@ public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false
* If $idMax equals 0, a deprecated debug message is logged
*
* @param int $id category ID
* @param string $idMax fail safe article ID
* @param numeric-string $idMax fail safe article ID
* @return int|false affected rows
*/
public function markReadCat(int $id, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) {
Expand Down Expand Up @@ -558,7 +558,7 @@ public function markReadCat(int $id, string $idMax = '0', ?FreshRSS_BooleanSearc
* If $idMax equals 0, a deprecated debug message is logged
*
* @param int $id_feed feed ID
* @param string $idMax fail safe article ID
* @param numeric-string $idMax fail safe article ID
* @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) {
Expand Down Expand Up @@ -612,7 +612,7 @@ public function markReadFeed(int $id_feed, string $idMax = '0', ?FreshRSS_Boolea
/**
* Mark all the articles in a tag as read.
* @param int $id tag ID, or empty for targeting any tag
* @param string $idMax max article ID
* @param numeric-string $idMax max article ID
* @return int|false affected rows
*/
public function markReadTag(int $id = 0, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null,
Expand Down Expand Up @@ -1206,7 +1206,7 @@ public function listWhere(string $type = 'a', int $id = 0, int $state = FreshRSS
}

/**
* @param array<string> $ids
* @param array<numeric-string> $ids
* @param 'ASC'|'DESC' $order
* @return Traversable<FreshRSS_Entry>
*/
Expand Down
Loading

0 comments on commit 5b28a35

Please sign in to comment.