Explorar o código

PHPStan more checkImplicitMixed (#7339)

* PHPStan more checkImplicitMixed

* Draft Entry.php

* Finish Entry.php

* Finish FeedDAO.php and Themes.php
Alexandre Alapetite hai 1 ano
pai
achega
f7b4a1e742

+ 15 - 11
app/Models/Entry.php

@@ -65,7 +65,9 @@ class FreshRSS_Entry extends Minz_Model {
 		}
 
 		$dao['attributes'] = empty($dao['attributes']) ? [] : json_decode($dao['attributes'], true);
-		if (!is_array($dao['attributes'])) {
+		if (is_array($dao['attributes'])) {
+			$dao['attributes'] = array_filter($dao['attributes'], 'is_string', ARRAY_FILTER_USE_KEY);
+		} else {
 			$dao['attributes'] = [];
 		}
 
@@ -168,7 +170,7 @@ class FreshRSS_Entry extends Minz_Model {
 		return preg_match('/(?P<delim>[\'"])' . preg_quote($link, '/') . '(?P=delim)/', $html) == 1;
 	}
 
-	/** @param array{'url'?:string,'length'?:int,'medium'?:string,'type'?:string} $enclosure */
+	/** @param array{url?:string,length?:int,medium?:string,type?:string} $enclosure */
 	private static function enclosureIsImage(array $enclosure): bool {
 		$elink = $enclosure['url'] ?? '';
 		$length = $enclosure['length'] ?? 0;
@@ -230,15 +232,15 @@ HTML;
 				continue;
 			}
 			$credits = $enclosure['credit'] ?? '';
-			$description = nl2br($enclosure['description'] ?? '', true);
-			$length = $enclosure['length'] ?? 0;
-			$medium = $enclosure['medium'] ?? '';
-			$mime = $enclosure['type'] ?? '';
+			$description = is_string($enclosure['description'] ?? null) ? nl2br($enclosure['description'], true) : '';
+			$length = is_numeric($enclosure['length'] ?? null) ? (int)$enclosure['length'] : 0;
+			$medium = is_string($enclosure['medium'] ?? null) ? $enclosure['medium'] : '';
+			$mime = is_string($enclosure['type'] ?? null) ? $enclosure['type'] : '';
 			$thumbnails = $enclosure['thumbnails'] ?? null;
 			if (!is_array($thumbnails)) {
 				$thumbnails = [];
 			}
-			$etitle = $enclosure['title'] ?? '';
+			$etitle = is_string($enclosure['title'] ?? null) ? $enclosure['title'] : '';
 
 			$content .= "\n";
 			$content .= '<figure class="enclosure">';
@@ -249,16 +251,16 @@ HTML;
 				}
 			}
 
-			if (self::enclosureIsImage($enclosure)) {
+			if (self::enclosureIsImage(['url' => $elink, 'length' => $length, 'medium' => $medium, 'type' => $mime])) {
 				$content .= '<p class="enclosure-content"><img src="' . $elink . '" alt="" title="' . $etitle . '" /></p>';
 			} elseif ($medium === 'audio' || str_starts_with($mime, 'audio')) {
 				$content .= '<p class="enclosure-content"><audio preload="none" src="' . $elink
-					. ($length == null ? '' : '" data-length="' . (int)$length)
+					. ($length == null ? '' : '" data-length="' . $length)
 					. ($mime == '' ? '' : '" data-type="' . htmlspecialchars($mime, ENT_COMPAT, 'UTF-8'))
 					. '" controls="controls" title="' . $etitle . '"></audio> <a download="" href="' . $elink . '">💾</a></p>';
 			} elseif ($medium === 'video' || str_starts_with($mime, 'video')) {
 				$content .= '<p class="enclosure-content"><video preload="none" src="' . $elink
-					. ($length == null ? '' : '" data-length="' . (int)$length)
+					. ($length == null ? '' : '" data-length="' . $length)
 					. ($mime == '' ? '' : '" data-type="' . htmlspecialchars($mime, ENT_COMPAT, 'UTF-8'))
 					. '" controls="controls" title="' . $etitle . '"></video> <a download="" href="' . $elink . '">💾</a></p>';
 			} else {	//e.g. application, text, unknown
@@ -273,7 +275,9 @@ HTML;
 					$credits = [$credits];
 				}
 				foreach ($credits as $credit) {
-					$content .= '<p class="enclosure-credits">© ' . $credit . '</p>';
+					if (is_string($credit)) {
+						$content .= '<p class="enclosure-credits">© ' . $credit . '</p>';
+					}
 				}
 			}
 			if ($description != '') {

+ 8 - 4
app/Models/FeedDAO.php

@@ -117,7 +117,9 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
 			// Merge existing and import attributes
 			$existingAttributes = $feed_search->attributes();
 			$importAttributes = $feed->attributes();
-			$feed->_attributes(array_replace_recursive($existingAttributes, $importAttributes));
+			$mergedAttributes = array_replace_recursive($existingAttributes, $importAttributes);
+			$mergedAttributes = array_filter($mergedAttributes, 'is_string', ARRAY_FILTER_USE_KEY);
+			$feed->_attributes($mergedAttributes);
 
 			// Update some values of the existing feed using the import
 			$values = [
@@ -382,8 +384,10 @@ SQL;
 			. 'ORDER BY `lastUpdate` '
 			. ($limit < 1 ? '' : 'LIMIT ' . intval($limit));
 		$stm = $this->pdo->query($sql);
-		if ($stm !== false) {
-			return self::daoToFeeds($stm->fetchAll(PDO::FETCH_ASSOC));
+		if ($stm !== false && ($res = $stm->fetchAll(PDO::FETCH_ASSOC)) !== false) {
+			/** @var list<array{id?:int,url?:string,kind?:int,category?:int,name?:string,website?:string,description?:string,lastUpdate?:int,priority?:int,
+			 * pathEntries?:string,httpAuth?:string,error?:int|bool,ttl?:int,attributes?:string,cache_nbUnreads?:int,cache_nbEntries?:int}> $res */
+			return self::daoToFeeds($res);
 		} else {
 			$info = $this->pdo->errorInfo();
 			/** @var array{0:string,1:int,2:string} $info */
@@ -613,6 +617,6 @@ SQL;
 			return -1;
 		}
 		$res = $stm->fetchAll(PDO::FETCH_COLUMN, 0);
-		return (int)($res[0] ?? 0);
+		return is_numeric($res[0] ?? null) ? (int)$res[0] : 0;
 	}
 }

+ 2 - 2
app/Models/Themes.php

@@ -92,14 +92,14 @@ class FreshRSS_Themes extends Minz_Model {
 	}
 
 	public static function title(string $name): string {
-		static $titles = [
+		$titles = [
 			'opml-dyn' => 'sub.category.dynamic_opml',
 		];
 		return $titles[$name] ?? '';
 	}
 
 	public static function alt(string $name): string {
-		static $alts = [
+		$alts = [
 			'add' => '➕',	//✚
 			'all' => '☰',
 			'bookmark-add' => '➕',	//✚

+ 15 - 2
app/views/helpers/feed/update.phtml

@@ -781,8 +781,14 @@
 					?>
 					</select>
 					<div class="stick">
+						<?php
+							$postFields = $this->feed->attributeArray('curl_params')[CURLOPT_POSTFIELDS] ?? '';
+							if (!is_string($postFields)) {
+								$postFields = '';
+							}
+						?>
 						<input type="text" name="curl_fields" id="curl_fields" value="<?=
-							htmlspecialchars($this->feed->attributeArray('curl_params')[CURLOPT_POSTFIELDS] ?? '', ENT_COMPAT, 'UTF-8')
+							htmlspecialchars($postFields, ENT_COMPAT, 'UTF-8')
 						?>" placeholder="<?= _t('sub.feed.method_postparams') ?>" />
 					</div>
 					<p class="help"><?= _i('help') ?> <?= _t('sub.feed.method_help') ?></p>
@@ -810,8 +816,15 @@
 			<div class="form-group">
 				<label class="group-name" for="http_headers"><?= _t('sub.feed.http_headers') ?></label>
 				<div class="group-controls">
+					<?php
+						$httpHeaders = $this->feed->attributeArray('curl_params')[CURLOPT_HTTPHEADER] ?? [];
+						if (!is_array($httpHeaders)) {
+							$httpHeaders = [];
+						}
+						$httpHeaders = array_filter($httpHeaders, 'is_string');
+					?>
 					<textarea class="valid-json" id="http_headers" name="http_headers" rows="3" cols="64" spellcheck="false"><?php
-						foreach ($this->feed->attributeArray('curl_params')[CURLOPT_HTTPHEADER] ?? [] as $header) {
+						foreach ($httpHeaders as $header) {
 							echo htmlspecialchars($header, ENT_NOQUOTES, 'UTF-8'), PHP_EOL;
 						}
 					?></textarea>

+ 0 - 4
phpstan-next.neon

@@ -10,10 +10,6 @@ parameters:
 	excludePaths:
 		analyse:
 			# TODO: Update files below and remove them from this list
-			- app/Models/Entry.php
 			- app/Models/EntryDAO.php
-			- app/Models/FeedDAO.php
 			- app/Models/TagDAO.php
-			- app/Models/Themes.php
 			- app/Services/ImportService.php
-			- app/views/helpers/feed/update.phtml