diff options
| author | 2023-03-22 09:57:31 +0100 | |
|---|---|---|
| committer | 2023-03-22 09:57:31 +0100 | |
| commit | e750448f5b32982170f81ca045f9f7e8dc8eed6f (patch) | |
| tree | 4053a9bfdcc5764cdc8ed93e9be73f54da7bd9d4 | |
| parent | 1a0616562db5c096dc7ca187f0210b3d57bffebf (diff) | |
Consistent entry ID type (32-bit compatibility) (#5213)
* Remove FreshRSS_Searchable for better types
The interface was not used, and it was preventing more precise types for the different `searchById()` methods, as they each have different input and output types.
* Consistent entry ID
Entry IDs (which are 64-bit integers) must be processed as string to be compatible with 32-bit platforms
* Fix type
* A few more related types
* PHPStan level 6
* Some more casts needed
* String cast for htmlspecialchars
| -rw-r--r-- | app/Controllers/feedController.php | 2 | ||||
| -rw-r--r-- | app/Controllers/importExportController.php | 2 | ||||
| -rw-r--r-- | app/Controllers/indexController.php | 4 | ||||
| -rw-r--r-- | app/Models/EntryDAO.php | 129 | ||||
| -rw-r--r-- | app/Models/EntryDAOPGSQL.php | 5 | ||||
| -rw-r--r-- | app/Models/EntryDAOSQLite.php | 18 | ||||
| -rw-r--r-- | app/Services/ExportService.php | 4 | ||||
| -rw-r--r-- | p/api/fever.php | 20 | ||||
| -rw-r--r-- | p/api/greader.php | 15 |
9 files changed, 112 insertions, 87 deletions
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 84f38fe5e..2fcc5eda6 100644 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -906,7 +906,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController { ]); //Get parameters. - $feed_id = Minz_Request::param('id'); + $feed_id = (int)(Minz_Request::param('id', 0)); $content_selector = trim(Minz_Request::param('selector')); if (!$content_selector) { diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php index 962abb160..5066ff124 100644 --- a/app/Controllers/importExportController.php +++ b/app/Controllers/importExportController.php @@ -357,7 +357,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController { // For each feed, check existing GUIDs already in database. $existingHashForGuids = array(); foreach ($newFeedGuids as $feedId => $newGuids) { - $existingHashForGuids[$feedId] = $this->entryDAO->listHashForFeedGuids(substr($feedId, 2), $newGuids); + $existingHashForGuids[$feedId] = $this->entryDAO->listHashForFeedGuids((int)substr($feedId, 2), $newGuids); } unset($newFeedGuids); diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index 9cb235d21..115117a8f 100644 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -251,10 +251,10 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController { $get = FreshRSS_Context::currentGet(true); if (is_array($get)) { $type = $get[0]; - $id = $get[1]; + $id = (int)($get[1]); } else { $type = $get; - $id = ''; + $id = 0; } $limit = FreshRSS_Context::$number; diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 0740f1ac4..6bb5394b2 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -10,7 +10,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { return true; } - protected static function sqlConcat($s1, $s2) { + protected static function sqlConcat(string $s1, string $s2): string { return 'CONCAT(' . $s1 . ',' . $s2 . ')'; //MySQL } @@ -27,7 +27,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { } //TODO: Move the database auto-updates to DatabaseDAO - protected function createEntryTempTable() { + protected function createEntryTempTable(): bool { $ok = false; $hadTransaction = $this->pdo->inTransaction(); if ($hadTransaction) { @@ -46,7 +46,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { return $ok; } - private function updateToMediumBlob() { + private function updateToMediumBlob(): bool { if ($this->pdo->dbType() !== 'mysql') { return false; } @@ -65,7 +65,7 @@ SQL; return $ok; } - protected function addColumn(string $name) { + protected function addColumn(string $name): bool { if ($this->pdo->inTransaction()) { $this->pdo->commit(); } @@ -85,7 +85,8 @@ SQL; } //TODO: Move the database auto-updates to DatabaseDAO - protected function autoUpdateDb(array $errorInfo) { + /** @param array<string> $errorInfo */ + protected function autoUpdateDb(array $errorInfo): bool { if (isset($errorInfo[0])) { if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_FIELD_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_COLUMN) { $errorLines = explode("\n", $errorInfo[2], 2); // The relevant column name is on the first line, other lines are noise @@ -119,7 +120,8 @@ SQL; */ private $addEntryPrepared = false; - public function addEntry(array $valuesTmp, bool $useTmpTable = true) { + /** @param array<string,string|int> $valuesTmp */ + public function addEntry(array $valuesTmp, bool $useTmpTable = true): bool { if ($this->addEntryPrepared == null) { $sql = static::sqlIgnoreConflict( 'INSERT INTO `_' . ($useTmpTable ? 'entrytmp' : 'entry') . '` (id, guid, title, author, ' @@ -190,7 +192,7 @@ SQL; } } - public function commitNewEntries() { + public function commitNewEntries(): bool { $sql = <<<'SQL' SET @rank=(SELECT MAX(id) - COUNT(*) FROM `_entrytmp`); @@ -215,9 +217,11 @@ SQL; return $result; } + /** @var PDOStatement|null */ private $updateEntryPrepared = null; - public function updateEntry(array $valuesTmp) { + /** @param array<string,string|int> $valuesTmp */ + public function updateEntry(array $valuesTmp): bool { if (!isset($valuesTmp['is_read'])) { $valuesTmp['is_read'] = null; } @@ -303,7 +307,7 @@ SQL; * @todo simplify the query by removing the str_repeat. I am pretty sure * there is an other way to do that. * - * @param integer|array $ids + * @param string|array<string> $ids * @return false|integer */ public function markFavorite($ids, bool $is_favorite = true) { @@ -392,7 +396,7 @@ SQL; * @todo remove code duplication. It seems the code is basically the * same if it is an array or not. * - * @param integer|array $ids + * @param string|array<string> $ids * @param boolean $is_read * @return integer|false affected rows */ @@ -465,12 +469,10 @@ SQL; * separated. * * @param string $idMax fail safe article ID - * @param boolean $onlyFavorites - * @param integer $priorityMin - * @param FreshRSS_BooleanSearch|null $filters * @return integer|false affected rows */ - public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false, int $priorityMin = 0, $filters = null, int $state = 0, bool $is_read = true) { + public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false, int $priorityMin = 0, + ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); if ($idMax == 0) { $idMax = time() . '000000'; @@ -511,10 +513,9 @@ SQL; * * @param integer $id category ID * @param string $idMax fail safe article ID - * @param FreshRSS_BooleanSearch|null $filters * @return integer|false affected rows */ - public function markReadCat(int $id, string $idMax = '0', $filters = null, int $state = 0, bool $is_read = true) { + public function markReadCat(int $id, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); if ($idMax == '0') { $idMax = time() . '000000'; @@ -550,10 +551,9 @@ SQL; * * @param integer $id_feed feed ID * @param string $idMax fail safe article ID - * @param FreshRSS_BooleanSearch|null $filters * @return integer|false affected rows */ - public function markReadFeed(int $id_feed, string $idMax = '0', $filters = null, int $state = 0, bool $is_read = true) { + public function markReadFeed(int $id_feed, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); if ($idMax == '0') { $idMax = time() . '000000'; @@ -601,7 +601,8 @@ SQL; * @param string $idMax max article ID * @return integer|false affected rows */ - public function markReadTag($id = 0, string $idMax = '0', $filters = null, int $state = 0, bool $is_read = true) { + public function markReadTag(int $id = 0, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, + int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); if ($idMax == '0') { $idMax = time() . '000000'; @@ -637,8 +638,10 @@ SQL; /** * Remember to call updateCachedValue($id_feed) or updateCachedValues() just after. + * @param array<string,int|bool|string> $options + * @return int|false */ - public function cleanOldEntries($id_feed, $options = []) { + public function cleanOldEntries(int $id_feed, array $options = []) { $sql = 'DELETE FROM `_entry` WHERE id_feed = :id_feed1'; //No alias for MySQL / MariaDB $params = []; $params[':id_feed1'] = $id_feed; @@ -697,6 +700,7 @@ SQL; } } + /** @return iterator<array<string,mixed>> */ public function selectAll() { $sql = 'SELECT id, guid, title, author, ' . (static::isCompressed() ? 'UNCOMPRESS(content_bin) AS content' : 'content') @@ -711,14 +715,13 @@ SQL; $info = $this->pdo->errorInfo(); if ($this->autoUpdateDb($info)) { yield from $this->selectAll(); + } else { + Minz_Log::error(__method__ . ' error: ' . json_encode($info)); } - Minz_Log::error(__method__ . ' error: ' . json_encode($info)); - yield false; } } - /** @return FreshRSS_Entry|null */ - public function searchByGuid($id_feed, $guid) { + public function searchByGuid(int $id_feed, string $guid): ?FreshRSS_Entry { // un guid est unique pour un flux donné $sql = 'SELECT id, guid, title, author, ' . (static::isCompressed() ? 'UNCOMPRESS(content_bin) AS content' : 'content') @@ -744,7 +747,7 @@ SQL; return isset($res[0]) ? FreshRSS_Entry::fromArray($res[0]) : null; } - public function searchIdByGuid($id_feed, $guid) { + public function searchIdByGuid(int $id_feed, string $guid): ?string { $sql = 'SELECT id FROM `_entry` WHERE id_feed=:id_feed AND guid=:guid'; $stm = $this->pdo->prepare($sql); $stm->bindParam(':id_feed', $id_feed, PDO::PARAM_INT); @@ -754,8 +757,8 @@ SQL; return isset($res[0]) ? $res[0] : null; } - /** @param FreshRSS_BooleanSearch $filters */ - public static function sqlBooleanSearch(string $alias, $filters, int $level = 0) { + /** @return array{0:array<int|string>,1:string} */ + public static function sqlBooleanSearch(string $alias, FreshRSS_BooleanSearch $filters, int $level = 0) { $search = ''; $values = []; @@ -1021,8 +1024,9 @@ SQL; return [ $values, $search ]; } - /** @param FreshRSS_BooleanSearch|null $filters */ - protected function sqlListEntriesWhere(string $alias = '', $filters = null, int $state = FreshRSS_Entry::STATE_ALL, + /** @return array{0:array<int|string>,1:string} */ + protected function sqlListEntriesWhere(string $alias = '', ?FreshRSS_BooleanSearch $filters = null, + int $state = FreshRSS_Entry::STATE_ALL, string $order = 'DESC', string $firstId = '', int $date_min = 0) { $search = ' '; $values = array(); @@ -1067,13 +1071,17 @@ SQL; return array($values, $search); } - private function sqlListWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, - $order = 'DESC', $limit = 1, $firstId = '', $filters = null, $date_min = 0) { + /** + * @param int $id category/feed/tag ID + * @return array{0:array<int|string>,1:string} + */ + private function sqlListWhere(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) { if (!$state) { $state = FreshRSS_Entry::STATE_ALL; } $where = ''; - $joinFeed = false; $values = array(); switch ($type) { case 'a': //All PRIORITY_MAIN_STREAM @@ -1092,15 +1100,15 @@ SQL; case 'c': //Category $where .= 'f.priority >= ' . FreshRSS_Feed::PRIORITY_NORMAL . ' '; $where .= 'AND f.category=? '; - $values[] = intval($id); + $values[] = $id; break; case 'f': //Feed $where .= 'e.id_feed=? '; - $values[] = intval($id); + $values[] = $id; break; case 't': //Tag (label) $where .= 'et.id_tag=? '; - $values[] = intval($id); + $values[] = $id; break; case 'T': //Any tag (label) $where .= '1=1 '; @@ -1126,8 +1134,13 @@ SQL; . ($limit > 0 ? ' LIMIT ' . intval($limit) : '')); //TODO: See http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/ } - private function listWhereRaw($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, - $order = 'DESC', $limit = 1, $firstId = '', $filters = null, $date_min = 0) { + /** + * @param int $id category/feed/tag ID + * @return PDOStatement|false + */ + private function listWhereRaw(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) { list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filters, $date_min); $sql = 'SELECT e0.id, e0.guid, e0.title, e0.author, ' @@ -1152,19 +1165,25 @@ SQL; } } - public function listWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, - $order = 'DESC', $limit = 1, $firstId = '', $filters = null, $date_min = 0) { + /** + * @param int $id category/feed/tag ID + * @return iterable<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) { $stm = $this->listWhereRaw($type, $id, $state, $order, $limit, $firstId, $filters, $date_min); if ($stm) { while ($row = $stm->fetch(PDO::FETCH_ASSOC)) { yield FreshRSS_Entry::fromArray($row); } - } else { - yield false; } } - /** @param array<string> $ids */ + /** + * @param array<string> $ids + * @return iterable<FreshRSS_Entry> + */ public function listByIds(array $ids, string $order = 'DESC') { if (count($ids) < 1) { return; @@ -1196,10 +1215,11 @@ SQL; /** * For API + * @param int $id category/feed/tag ID * @return array<string>|false */ - public function listIdsWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, - $order = 'DESC', $limit = 1, $firstId = '', $filters = null) { + public function listIdsWhere(string $type = 'a', int $id = 0, int $state = FreshRSS_Entry::STATE_ALL, + string $order = 'DESC', int $limit = 1, string $firstId = '', ?FreshRSS_BooleanSearch $filters = null) { [$values, $sql] = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filters); $stm = $this->pdo->prepare($sql); @@ -1208,7 +1228,11 @@ SQL; return $stm->fetchAll(PDO::FETCH_COLUMN, 0) ?: []; } - public function listHashForFeedGuids($id_feed, $guids) { + /** + * @param array<string> $guids + * @return array<string>|false + */ + public function listHashForFeedGuids(int $id_feed, array $guids) { $result = []; if (count($guids) < 1) { return $result; @@ -1244,12 +1268,10 @@ SQL; } /** - * @param int $id_feed * @param array<string> $guids - * @param int $mtime * @return int|false The number of affected feeds, or false if error */ - public function updateLastSeen($id_feed, $guids, $mtime = 0) { + public function updateLastSeen(int $id_feed, array $guids, int $mtime = 0) { if (count($guids) < 1) { return 0; } elseif (count($guids) > FreshRSS_DatabaseDAO::MAX_VARIABLE_NUMBER) { @@ -1281,6 +1303,7 @@ SQL; } } + /** @return array<string,int>|false */ public function countUnreadRead() { $sql = 'SELECT COUNT(e.id) AS count FROM `_entry` e INNER JOIN `_feed` f ON e.id_feed=f.id WHERE f.priority > 0' . ' UNION SELECT COUNT(e.id) AS count FROM `_entry` e INNER JOIN `_feed` f ON e.id_feed=f.id WHERE f.priority > 0 AND e.is_read=0'; @@ -1295,11 +1318,12 @@ SQL; return array('all' => $all, 'unread' => $unread, 'read' => $all - $unread); } - public function count($minPriority = null) { + /** @return int|false */ + public function count(?int $minPriority = null) { $sql = 'SELECT COUNT(e.id) AS count FROM `_entry` e'; if ($minPriority !== null) { $sql .= ' INNER JOIN `_feed` f ON e.id_feed=f.id'; - $sql .= ' WHERE f.priority > ' . intval($minPriority); + $sql .= ' WHERE f.priority > ' . $minPriority; } $stm = $this->pdo->query($sql); if ($stm == false) { @@ -1309,20 +1333,21 @@ SQL; return isset($res[0]) ? intval($res[0]) : 0; } - public function countNotRead($minPriority = null) { + public function countNotRead(?int $minPriority = null): int { $sql = 'SELECT COUNT(e.id) AS count FROM `_entry` e'; if ($minPriority !== null) { $sql .= ' INNER JOIN `_feed` f ON e.id_feed=f.id'; } $sql .= ' WHERE e.is_read=0'; if ($minPriority !== null) { - $sql .= ' AND f.priority > ' . intval($minPriority); + $sql .= ' AND f.priority > ' . $minPriority; } $stm = $this->pdo->query($sql); $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); return isset($res[0]) ? intval($res[0]) : 0; } + /** @return array<string,int>|false */ public function countUnreadReadFavorites() { $sql = <<<'SQL' SELECT c FROM ( diff --git a/app/Models/EntryDAOPGSQL.php b/app/Models/EntryDAOPGSQL.php index 8702db706..4c3c50056 100644 --- a/app/Models/EntryDAOPGSQL.php +++ b/app/Models/EntryDAOPGSQL.php @@ -18,7 +18,8 @@ class FreshRSS_EntryDAOPGSQL extends FreshRSS_EntryDAOSQLite { return rtrim($sql, ' ;') . ' ON CONFLICT DO NOTHING'; } - protected function autoUpdateDb(array $errorInfo) { + /** @param array<string> $errorInfo */ + protected function autoUpdateDb(array $errorInfo): bool { if (isset($errorInfo[0])) { if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_FIELD_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_COLUMN) { $errorLines = explode("\n", $errorInfo[2], 2); // The relevant column name is on the first line, other lines are noise @@ -40,7 +41,7 @@ class FreshRSS_EntryDAOPGSQL extends FreshRSS_EntryDAOSQLite { return false; } - public function commitNewEntries() { + public function commitNewEntries(): bool { //TODO: Update to PostgreSQL 9.5+ syntax with ON CONFLICT DO NOTHING $sql = 'DO $$ DECLARE diff --git a/app/Models/EntryDAOSQLite.php b/app/Models/EntryDAOSQLite.php index 35f3ef676..e509097f2 100644 --- a/app/Models/EntryDAOSQLite.php +++ b/app/Models/EntryDAOSQLite.php @@ -10,7 +10,7 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { return false; } - protected static function sqlConcat($s1, $s2) { + protected static function sqlConcat(string $s1, string $s2): string { return $s1 . '||' . $s2; } @@ -22,7 +22,8 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { return str_replace('INSERT INTO ', 'INSERT OR IGNORE INTO ', $sql); } - protected function autoUpdateDb(array $errorInfo) { + /** @param array<string> $errorInfo */ + protected function autoUpdateDb(array $errorInfo): bool { if ($tableInfo = $this->pdo->query("PRAGMA table_info('entry')")) { $columns = $tableInfo->fetchAll(PDO::FETCH_COLUMN, 1); foreach (['attributes'] as $column) { @@ -47,7 +48,7 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { return false; } - public function commitNewEntries() { + public function commitNewEntries(): bool { $sql = ' DROP TABLE IF EXISTS `tmp`; CREATE TEMP TABLE `tmp` AS @@ -115,7 +116,7 @@ DROP TABLE IF EXISTS `tmp`; * @todo remove code duplication. It seems the code is basically the * same if it is an array or not. * - * @param integer|array $ids + * @param string|array<string> $ids * @param boolean $is_read * @return integer|false affected rows */ @@ -177,10 +178,10 @@ DROP TABLE IF EXISTS `tmp`; * @param string $idMax fail safe article ID * @param boolean $onlyFavorites * @param integer $priorityMin - * @param FreshRSS_BooleanSearch|null $filters * @return integer|false affected rows */ - public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false, int $priorityMin = 0, $filters = null, int $state = 0, bool $is_read = true) { + public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false, int $priorityMin = 0, + ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); if ($idMax == '0') { $idMax = time() . '000000'; @@ -219,10 +220,9 @@ DROP TABLE IF EXISTS `tmp`; * * @param integer $id category ID * @param string $idMax fail safe article ID - * @param FreshRSS_BooleanSearch|null $filters * @return integer|false affected rows */ - public function markReadCat(int $id, string $idMax = '0', $filters = null, int $state = 0, bool $is_read = true) { + public function markReadCat(int $id, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); if ($idMax == '0') { $idMax = time() . '000000'; @@ -256,7 +256,7 @@ DROP TABLE IF EXISTS `tmp`; * @param string $idMax max article ID * @return integer|false affected rows */ - public function markReadTag($id = 0, string $idMax = '0', $filters = null, int $state = 0, bool $is_read = true) { + public function markReadTag($id = 0, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) { FreshRSS_UserDAO::touch(); if ($idMax == 0) { $idMax = time() . '000000'; diff --git a/app/Services/ExportService.php b/app/Services/ExportService.php index 6b0a3f178..b09be1011 100644 --- a/app/Services/ExportService.php +++ b/app/Services/ExportService.php @@ -76,12 +76,12 @@ class FreshRSS_Export_Service { $view->list_title = _t('sub.import_export.starred_list'); $view->type = 'starred'; $entriesId = $this->entry_dao->listIdsWhere( - $type, '', FreshRSS_Entry::STATE_ALL, 'ASC', -1 + $type, 0, FreshRSS_Entry::STATE_ALL, 'ASC', -1 ); $view->entryIdsTagNames = $this->tag_dao->getEntryIdsTagNames($entriesId); // The following is a streamable query, i.e. must be last $view->entries = $this->entry_dao->listWhere( - $type, '', FreshRSS_Entry::STATE_ALL, 'ASC', -1 + $type, 0, FreshRSS_Entry::STATE_ALL, 'ASC', -1 ); return [ diff --git a/p/api/fever.php b/p/api/fever.php index 1bc7068ab..7afe843e9 100644 --- a/p/api/fever.php +++ b/p/api/fever.php @@ -227,8 +227,8 @@ final class FeverAPI } if (isset($_REQUEST['mark'], $_REQUEST['as'], $_REQUEST['id']) && ctype_digit($_REQUEST['id'])) { - $id = intval($_REQUEST['id']); - $before = intval($_REQUEST['before'] ?? '0'); + $id = (string)$_REQUEST['id']; + $before = (int)($_REQUEST['before'] ?? '0'); switch (strtolower($_REQUEST['mark'])) { case 'item': switch ($_REQUEST['as']) { @@ -249,14 +249,14 @@ final class FeverAPI case 'feed': switch ($_REQUEST['as']) { case 'read': - $this->setFeedAsRead($id, $before); + $this->setFeedAsRead((int)$id, $before); break; } break; case 'group': switch ($_REQUEST['as']) { case 'read': - $this->setGroupAsRead($id, $before); + $this->setGroupAsRead((int)$id, $before); break; } break; @@ -420,40 +420,40 @@ final class FeverAPI } private function getUnreadItemIds(): string { - $entries = $this->entryDAO->listIdsWhere('a', '', FreshRSS_Entry::STATE_NOT_READ, 'ASC', 0) ?: []; + $entries = $this->entryDAO->listIdsWhere('a', 0, FreshRSS_Entry::STATE_NOT_READ, 'ASC', 0) ?: []; return $this->entriesToIdList($entries); } private function getSavedItemIds(): string { - $entries = $this->entryDAO->listIdsWhere('a', '', FreshRSS_Entry::STATE_FAVORITE, 'ASC', 0) ?: []; + $entries = $this->entryDAO->listIdsWhere('a', 0, FreshRSS_Entry::STATE_FAVORITE, 'ASC', 0) ?: []; return $this->entriesToIdList($entries); } /** * @return integer|false */ - private function setItemAsRead(int $id) { + private function setItemAsRead(string $id) { return $this->entryDAO->markRead($id, true); } /** * @return integer|false */ - private function setItemAsUnread(int $id) { + private function setItemAsUnread(string $id) { return $this->entryDAO->markRead($id, false); } /** * @return integer|false */ - private function setItemAsSaved(int $id) { + private function setItemAsSaved(string $id) { return $this->entryDAO->markFavorite($id, true); } /** * @return integer|false */ - private function setItemAsUnsaved(int $id) { + private function setItemAsUnsaved(string $id) { return $this->entryDAO->markFavorite($id, false); } diff --git a/p/api/greader.php b/p/api/greader.php index 069f37b65..a4b542c23 100644 --- a/p/api/greader.php +++ b/p/api/greader.php @@ -385,10 +385,6 @@ final class GReaderAPI { self::badRequest(); } $addCatId = 0; - $categoryDAO = null; - if ($add != '' || $remove != '') { - $categoryDAO = FreshRSS_Factory::createCategoryDao(); - } $c_name = ''; if ($add != '' && strpos($add, 'user/') === 0) { //user/-/label/Example ; user/username/label/Example if (strpos($add, 'user/-/label/') === 0) { @@ -403,6 +399,7 @@ final class GReaderAPI { } } $c_name = htmlspecialchars($c_name, ENT_COMPAT, 'UTF-8'); + $categoryDAO = FreshRSS_Factory::createCategoryDao(); $cat = $categoryDAO->searchByName($c_name); $addCatId = $cat == null ? 0 : $cat->id(); } elseif ($remove != '' && strpos($remove, 'user/-/label/') === 0) { @@ -586,13 +583,14 @@ final class GReaderAPI { } /** - * @return array<string|int|FreshRSS_BooleanSearch> + * @param string|int $streamId + * @return array{string,int,int,FreshRSS_BooleanSearch} */ - private static function streamContentsFilters(string $type, string $streamId, + private static function streamContentsFilters(string $type, $streamId, string $filter_target, string $exclude_target, int $start_time, int $stop_time): array { switch ($type) { case 'f': //feed - if ($streamId != '' && !ctype_digit($streamId)) { + if ($streamId != '' && is_string($streamId) && !ctype_digit($streamId)) { $feedDAO = FreshRSS_Factory::createFeedDao(); $streamId = htmlspecialchars($streamId, ENT_COMPAT, 'UTF-8'); $feed = $feedDAO->searchByUrl($streamId); @@ -601,7 +599,7 @@ final class GReaderAPI { break; case 'c': //category or label $categoryDAO = FreshRSS_Factory::createCategoryDao(); - $streamId = htmlspecialchars($streamId, ENT_COMPAT, 'UTF-8'); + $streamId = htmlspecialchars((string)$streamId, ENT_COMPAT, 'UTF-8'); $cat = $categoryDAO->searchByName($streamId); if ($cat != null) { $type = 'c'; @@ -619,6 +617,7 @@ final class GReaderAPI { } break; } + $streamId = (int)$streamId; switch ($filter_target) { case 'user/-/state/com.google/read': |
