Explorar o código

Fix PHP 7 compatibility strict_types (#5893)

* Fix PHP 7 compatibility
https://github.com/FreshRSS/FreshRSS/discussions/5892

* Multiple PHP 7 fixes

* PHPStan
Alexandre Alapetite %!s(int64=2) %!d(string=hai) anos
pai
achega
b65ea97901

+ 1 - 1
Docker/Dockerfile-Oldest

@@ -7,7 +7,7 @@ RUN apk add --no-cache \
 	tzdata \
 	apache2 php7-apache2 \
 	php7 php7-curl php7-gmp php7-intl php7-mbstring php7-xml php7-zip \
-	php7-ctype php7-dom php7-iconv php7-json php7-opcache php7-openssl php7-phar php7-session php7-simplexml php7-xmlreader php7-xmlwriter php7-xml php7-tokenizer php7-zlib \
+	php7-ctype php7-dom php7-fileinfo php7-iconv php7-json php7-opcache php7-openssl php7-phar php7-session php7-simplexml php7-xmlreader php7-xmlwriter php7-xml php7-tokenizer php7-zlib \
 	php7-pdo_sqlite php7-pdo_mysql php7-pdo_pgsql
 
 RUN mkdir -p /var/www/FreshRSS /run/apache2/

+ 5 - 2
app/Models/CategoryDAO.php

@@ -435,6 +435,8 @@ SQL;
 		$feedsDao = [];
 		$feedDao = FreshRSS_Factory::createFeedDao();
 		foreach ($listDAO as $line) {
+			FreshRSS_DatabaseDAO::pdoInt($line, ['c_id', 'c_kind', 'c_last_update', 'c_error',
+				'id', 'kind', 'priority', 'error', 'cache_nbEntries', 'cache_nbUnreads', 'ttl']);
 			if (!empty($previousLine['c_id']) && $line['c_id'] !== $previousLine['c_id']) {
 				// End of the current category, we add it to the $list
 				$cat = new FreshRSS_Category(
@@ -444,7 +446,7 @@ SQL;
 				$cat->_id($previousLine['c_id']);
 				$cat->_kind($previousLine['c_kind']);
 				$cat->_attributes('', $previousLine['c_attributes'] ?? '[]');
-				$list[$previousLine['c_id']] = $cat;
+				$list[(int)$previousLine['c_id']] = $cat;
 
 				$feedsDao = [];	//Prepare for next category
 			}
@@ -464,7 +466,7 @@ SQL;
 			$cat->_lastUpdate($previousLine['c_last_update'] ?? 0);
 			$cat->_error($previousLine['c_error'] ?? 0);
 			$cat->_attributes('', $previousLine['c_attributes'] ?? []);
-			$list[$previousLine['c_id']] = $cat;
+			$list[(int)$previousLine['c_id']] = $cat;
 		}
 
 		return $list;
@@ -478,6 +480,7 @@ SQL;
 		$list = [];
 
 		foreach ($listDAO as $dao) {
+			FreshRSS_DatabaseDAO::pdoInt($dao, ['id', 'kind', 'lastUpdate', 'error']);
 			$cat = new FreshRSS_Category(
 				$dao['name']
 			);

+ 14 - 0
app/Models/DatabaseDAO.php

@@ -393,4 +393,18 @@ SQL;
 
 		return true;
 	}
+
+	/**
+	 * Ensure that some PDO columns are `int` and not `string`.
+	 * Compatibility with PHP 7.
+	 * @param array<string|int|null> $table
+	 * @param array<string> $columns
+	 */
+	public static function pdoInt(array &$table, array $columns): void {
+		foreach ($columns as $column) {
+			if (isset($table[$column]) && is_string($table[$column])) {
+				$table[$column] = (int)$table[$column];
+			}
+		}
+	}
 }

+ 2 - 0
app/Models/Entry.php

@@ -52,6 +52,8 @@ class FreshRSS_Entry extends Minz_Model {
 	/** @param array{'id'?:string,'id_feed'?:int,'guid'?:string,'title'?:string,'author'?:string,'content'?:string,'link'?:string,'date'?:int|string,'lastSeen'?:int,
 	 *		'hash'?:string,'is_read'?:bool|int,'is_favorite'?:bool|int,'tags'?:string|array<string>,'attributes'?:string,'thumbnail'?:string,'timestamp'?:string} $dao */
 	public static function fromArray(array $dao): FreshRSS_Entry {
+		FreshRSS_DatabaseDAO::pdoInt($dao, ['id_feed', 'date', 'lastSeen', 'is_read', 'is_favorite']);
+
 		if (empty($dao['content'])) {
 			$dao['content'] = '';
 		}

+ 2 - 1
app/Models/FeedDAO.php

@@ -584,6 +584,7 @@ SQL;
 		$list = [];
 
 		foreach ($listDAO as $key => $dao) {
+			FreshRSS_DatabaseDAO::pdoInt($dao, ['id', 'kind', 'category', 'lastUpdate', 'priority', 'error', 'ttl', 'cache_nbUnreads', 'cache_nbEntries']);
 			if (!isset($dao['name'])) {
 				continue;
 			}
@@ -627,6 +628,6 @@ SQL;
 			return -1;
 		}
 		$res = $stm->fetchAll(PDO::FETCH_COLUMN, 0);
-		return $res[0] ?? 0;
+		return (int)($res[0] ?? 0);
 	}
 }

+ 21 - 4
app/Models/StatsDAO.php

@@ -49,8 +49,13 @@ WHERE e.id_feed = f.id
 {$filter}
 SQL;
 		$res = $this->fetchAssoc($sql);
-		/** @var array<array{'total':int,'count_unreads':int,'count_reads':int,'count_favorites':int}>|null $res */
-		return $res[0] ?? false;
+		if (!empty($res[0])) {
+			$dao = $res[0];
+			/** @var array<array{'total':int,'count_unreads':int,'count_reads':int,'count_favorites':int}> $res */
+			FreshRSS_DatabaseDAO::pdoInt($dao, ['total', 'count_unreads', 'count_reads', 'count_favorites']);
+			return $dao;
+		}
+		return false;
 	}
 
 	/**
@@ -286,7 +291,13 @@ LIMIT 10
 SQL;
 		$res = $this->fetchAssoc($sql);
 		/** @var array<array{'id':int,'name':string,'category':string,'count':int}>|null $res */
-		return $res == null ? [] : $res;
+		if (is_array($res)) {
+			foreach ($res as &$dao) {
+				FreshRSS_DatabaseDAO::pdoInt($dao, ['id', 'count']);
+			}
+			return $res;
+		}
+		return [];
 	}
 
 	/**
@@ -306,7 +317,13 @@ ORDER BY name
 SQL;
 		$res = $this->fetchAssoc($sql);
 		/** @var array<array{'id':int,'name':string,'last_date':int,'nb_articles':int}>|null $res */
-		return $res == null ? [] : $res;
+		if (is_array($res)) {
+			foreach ($res as &$dao) {
+				FreshRSS_DatabaseDAO::pdoInt($dao, ['id', 'last_date', 'nb_articles']);
+			}
+			return $res;
+		}
+		return [];
 	}
 
 	/**

+ 1 - 1
app/actualize_script.php

@@ -1,6 +1,6 @@
 #!/usr/bin/env php
 <?php
-declare(strict_types=1);
+// declare(strict_types=1);	// Need to wait for PHP 8+ due to https://php.net/ob-implicit-flush
 require(__DIR__ . '/../cli/_cli.php');
 
 session_cache_limiter('');

+ 1 - 1
lib/lib_rss.php

@@ -171,7 +171,7 @@ function escapeToUnicodeAlternative(string $text, bool $extended = true): string
 function format_number($n, int $precision = 0): string {
 	// number_format does not seem to be Unicode-compatible
 	return str_replace(' ', ' ',	// Thin non-breaking space
-		number_format($n, $precision, '.', ' ')
+		number_format((float)$n, $precision, '.', ' ')
 	);
 }