Bläddra i källkod

Use strict equality when comparing strings

microsub
J. King 5 år sedan
förälder
incheckning
81acba90dc
  1. 2
      arsse.php
  2. 2
      lib/AbstractException.php
  3. 2
      lib/CLI.php
  4. 2
      lib/Conf.php
  5. 2
      lib/Database.php
  6. 4
      lib/Db/AbstractDriver.php
  7. 8
      lib/Db/MySQL/Driver.php
  8. 6
      lib/Db/MySQL/Statement.php
  9. 2
      lib/Db/PDOError.php
  10. 20
      lib/Feed.php
  11. 18
      lib/Lang.php
  12. 4
      lib/Misc/Date.php
  13. 10
      lib/Misc/ValueInfo.php
  14. 22
      lib/REST.php
  15. 2
      lib/REST/AbstractHandler.php
  16. 12
      lib/REST/NextCloudNews/V1_2.php
  17. 14
      lib/REST/Target.php
  18. 28
      lib/REST/TinyTinyRSS/API.php
  19. 2
      lib/REST/TinyTinyRSS/Icon.php
  20. 6
      tests/cases/CLI/TestCLI.php
  21. 2
      tests/cases/Db/BaseDriver.php
  22. 8
      tests/cases/Db/BaseStatement.php
  23. 2
      tests/cases/Db/MySQLPDO/TestStatement.php
  24. 2
      tests/cases/Db/PostgreSQL/TestCreation.php
  25. 2
      tests/cases/Db/PostgreSQL/TestStatement.php
  26. 2
      tests/cases/Db/PostgreSQLPDO/TestCreation.php
  27. 2
      tests/cases/Db/PostgreSQLPDO/TestStatement.php
  28. 4
      tests/cases/Db/SQLite3PDO/TestStatement.php
  29. 10
      tests/cases/REST/TinyTinyRSS/TestAPI.php
  30. 4
      tests/cases/User/TestUser.php
  31. 8
      tests/lib/DatabaseInformation.php

2
arsse.php

@ -14,7 +14,7 @@ ini_set("memory_limit", "-1");
ini_set("max_execution_time", "0");
if (\PHP_SAPI=="cli") {
if (\PHP_SAPI === "cli") {
// initialize the CLI; this automatically handles --help and --version
$cli = new CLI;
// handle other CLI requests; some do not require configuration

2
lib/AbstractException.php

@ -83,7 +83,7 @@ abstract class AbstractException extends \Exception {
];
public function __construct(string $msgID = "", $vars = null, \Throwable $e = null) {
if ($msgID=="") {
if ($msgID === "") {
$msg = "Exception.unknown";
$code = 10000;
} else {

2
lib/CLI.php

@ -74,7 +74,7 @@ USAGE_TEXT;
return (int) !Arsse::$db->feedUpdate((int) $args['<n>'], true);
case "conf save-defaults":
$file = $args['<file>'];
$file = ($file=="-" ? null : $file) ?? "php://output";
$file = ($file === "-" ? null : $file) ?? "php://output";
return (int) !($this->getConf())->exportFile($file, true);
case "user":
$this->loadConf();

2
lib/Conf.php

@ -115,7 +115,7 @@ class Conf {
* @param string $import_file Optional file to read configuration data from
* @see self::importFile() */
public function __construct(string $import_file = "") {
if ($import_file != "") {
if ($import_file !== "") {
$this->importFile($import_file);
}
}

2
lib/Database.php

@ -364,7 +364,7 @@ class Database {
$parent = (int) $parent;
}
// if the target parent is the folder itself, this is a circular dependence
if ($id==$parent) {
if ($id == $parent) {
throw new Db\ExceptionInput("circularDependence", $errData);
}
// make sure both that the prospective parent exists, and that the it is not one of its children (a circular dependence);

4
lib/Db/AbstractDriver.php

@ -131,7 +131,7 @@ abstract class AbstractDriver implements Driver {
default:
throw new Exception("savepointStatusUnknown", $this->transStatus[$index]); // @codeCoverageIgnore
}
if ($index==$this->transDepth) {
if ($index == $this->transDepth) {
// if we've released the topmost savepoint, clean up all prior savepoints which have already been explicitly committed (or rolled back), if any
while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) {
array_pop($this->transStatus);
@ -185,7 +185,7 @@ abstract class AbstractDriver implements Driver {
default:
throw new Exception("savepointStatusUnknown", $this->transStatus[$index]); // @codeCoverageIgnore
}
if ($index==$this->transDepth) {
if ($index == $this->transDepth) {
while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) {
array_pop($this->transStatus);
$this->transDepth--;

8
lib/Db/MySQL/Driver.php

@ -29,11 +29,11 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
throw new Exception("extMissing", static::driverName()); // @codeCoverageIgnore
}
$host = Arsse::$conf->dbMySQLHost;
if ($host[0] == "/") {
if ($host[0] === "/") {
// host is a Unix socket
$socket = $host;
$host = "";
} elseif(substr($host, 0, 9) == "\\\\.\\pipe\\") {
} elseif(substr($host, 0, 9) === "\\\\.\\pipe\\") {
// host is a Windows named piple
$socket = substr($host, 10);
$host = "";
@ -183,8 +183,8 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
protected function dispatch(string $query) {
$r = $this->db->query($query);
if ($this->db->sqlstate != "00000") {
if ($this->db->sqlstate == "HY000") {
if ($this->db->sqlstate !== "00000") {
if ($this->db->sqlstate === "HY000") {
list($excClass, $excMsg, $excData) = $this->buildEngineException($this->db->errno, $this->db->error);
} else {
list($excClass, $excMsg, $excData) = $this->buildStandardException($this->db->sqlstate, $this->db->error);

6
lib/Db/MySQL/Statement.php

@ -65,8 +65,8 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement {
$this->types = "";
$this->values = [];
// check for errors
if ($this->st->sqlstate != "00000") {
if ($this->st->sqlstate == "HY000") {
if ($this->st->sqlstate !== "00000") {
if ($this->st->sqlstate === "HY000") {
list($excClass, $excMsg, $excData) = $this->buildEngineException($this->st->errno, $this->st->error);
} else {
list($excClass, $excMsg, $excData) = $this->buildStandardException($this->st->sqlstate, $this->st->error);
@ -98,7 +98,7 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement {
$out = "";
for ($b = 1; $b < sizeof($query); $b++) {
$a = $b - 1;
$mark = (($types[$a] ?? "") == "datetime") ? "cast(? as datetime(0))" : "?";
$mark = (($types[$a] ?? "") === "datetime") ? "cast(? as datetime(0))" : "?";
$out .= $query[$a].$mark;
}
$out .= array_pop($query);

2
lib/Db/PDOError.php

@ -15,7 +15,7 @@ trait PDOError {
} else {
$err = $this->db->errorInfo();
}
if ($err[0]=="HY000") {
if ($err[0] === "HY000") {
return static::buildEngineException($err[1], $err[2]);
} else {
return static::buildStandardException($err[0], $err[2]);

20
lib/Feed.php

@ -135,19 +135,19 @@ class Feed {
// id doesn't exist.
$content = $f->content.$f->enclosureUrl.$f->enclosureType;
// if the item link URL and item title are both equal to the feed link URL, then the item has neither a link URL nor a title
if ($f->url==$feed->siteUrl && $f->title==$feed->siteUrl) {
if ($f->url === $feed->siteUrl && $f->title === $feed->siteUrl) {
$f->urlTitleHash = "";
} else {
$f->urlTitleHash = hash('sha256', $f->url.$f->title);
}
// if the item link URL is equal to the feed link URL, it has no link URL; if there is additionally no content, these should not be hashed
if (!strlen($content) && $f->url==$feed->siteUrl) {
if (!strlen($content) && $f->url === $feed->siteUrl) {
$f->urlContentHash = "";
} else {
$f->urlContentHash = hash('sha256', $f->url.$content);
}
// if the item's title is the same as its link URL, it has no title; if there is additionally no content, these should not be hashed
if (!strlen($content) && $f->title==$f->url) {
if (!strlen($content) && $f->title === $f->url) {
$f->titleContentHash = "";
} else {
$f->titleContentHash = hash('sha256', $f->title.$content);
@ -215,15 +215,15 @@ class Feed {
foreach ($items as $item) {
foreach ($out as $index => $check) {
// if the two items both have IDs and they differ, they do not match, regardless of hashes
if ($item->id && $check->id && $item->id != $check->id) {
if ($item->id && $check->id && $item->id !== $check->id) {
continue;
}
// if the two items have the same ID or any one hash matches, they are two versions of the same item
if (
($item->id && $check->id && $item->id == $check->id) ||
($item->urlTitleHash && $item->urlTitleHash == $check->urlTitleHash) ||
($item->urlContentHash && $item->urlContentHash == $check->urlContentHash) ||
($item->titleContentHash && $item->titleContentHash == $check->titleContentHash)
($item->id && $check->id && $item->id === $check->id) ||
($item->urlTitleHash && $item->urlTitleHash === $check->urlTitleHash) ||
($item->urlContentHash && $item->urlContentHash === $check->urlContentHash) ||
($item->titleContentHash && $item->titleContentHash === $check->titleContentHash)
) {
if (// because newsfeeds are usually order newest-first, the later item should only be used if...
// the later item has an update date and the existing item does not
@ -346,9 +346,9 @@ class Feed {
$diff = $dates[$a] - $dates[$a+1];
$offsets[] = $this->normalizeDateDiff($diff);
}
if ($offsets[0]==$offsets[1] || $offsets[0]==$offsets[2]) {
if ($offsets[0] === $offsets[1] || $offsets[0] === $offsets[2]) {
return $now->modify("+".$offsets[0]);
} elseif ($offsets[1]==$offsets[2]) {
} elseif ($offsets[1] === $offsets[2]) {
return $now->modify("+".$offsets[1]);
} else {
return $now->modify("+ 1 hour");

18
lib/Lang.php

@ -37,14 +37,14 @@ class Lang {
$this->checkRequirements();
}
// if requesting the same locale as already wanted, just return (but load first if we've requested an immediate load)
if ($locale==$this->wanted) {
if ($locale === $this->wanted) {
if ($immediate && !$this->synched) {
$this->load();
}
return $locale;
}
// if we've requested a locale other than the null locale, fetch the list of available files and find the closest match e.g. en_ca_somedialect -> en_ca
if ($locale != "") {
if ($locale !== "") {
$list = $this->listFiles();
// if the default locale is unavailable, this is (for now) an error
if (!in_array(self::DEFAULT, $list)) {
@ -81,7 +81,7 @@ class Lang {
try {
$this->load();
} catch (Lang\Exception $e) {
if ($this->wanted==self::DEFAULT) {
if ($this->wanted === self::DEFAULT) {
$this->set("", true);
} else {
throw $e;
@ -112,14 +112,14 @@ class Lang {
$out = [];
$files = $this->listFiles();
foreach ($files as $tag) {
$out[$tag] = \Locale::getDisplayName($tag, ($locale=="") ? $tag : $locale);
$out[$tag] = \Locale::getDisplayName($tag, ($locale === "") ? $tag : $locale);
}
return $out;
}
public function match(string $locale, array $list = null): string {
$list = $list ?? $this->listFiles();
$default = ($this->locale=="") ? self::DEFAULT : $this->locale;
$default = ($this->locale === "") ? self::DEFAULT : $this->locale;
return \Locale::lookup($list, $locale, true, $default);
}
@ -155,7 +155,7 @@ class Lang {
$this->checkRequirements();
}
// if we've requested no locale (""), just load the fallback strings and return
if ($this->wanted=="") {
if ($this->wanted === "") {
$this->strings = self::REQUIRED;
$this->locale = $this->wanted;
$this->synched = true;
@ -169,7 +169,7 @@ class Lang {
$tag = array_pop($tags);
}
// include the default locale as the base if the most general locale requested is not the default
if ($tag != self::DEFAULT) {
if ($tag !== self::DEFAULT) {
$files[] = self::DEFAULT;
}
// save the list of files to be loaded for later reference
@ -177,14 +177,14 @@ class Lang {
// reduce the list of files to be loaded to the minimum necessary (e.g. if we go from "fr" to "fr_ca", we don't need to load "fr" or "en")
$files = [];
foreach ($loaded as $file) {
if ($file==$this->locale) {
if ($file === $this->locale) {
break;
}
$files[] = $file;
}
// if we need to load all files, start with the fallback strings
$strings = [];
if ($files==$loaded) {
if ($files === $loaded) {
$strings[] = self::REQUIRED;
} else {
// otherwise start with the strings we already have if we're going from e.g. "fr" to "fr_ca"

4
lib/Misc/Date.php

@ -13,9 +13,9 @@ class Date {
return null;
}
$out = ValueInfo::normalize($date, ValueInfo::T_STRING, null, $outFormat);
if ($outFormat=="unix") {
if ($outFormat === "unix") {
$out = (int) $out;
} elseif ($outFormat=="float") {
} elseif ($outFormat === "float") {
$out = (float) $out;
}
return $out;

10
lib/Misc/ValueInfo.php

@ -157,7 +157,7 @@ class ValueInfo {
return $out;
} else {
$out = sprintf("%F", $value);
return substr($out, -2)==".0" ? (string) (int) $out : $out;
return preg_match("/\.0{1,}$/", $out) ? (string) (int) $out : $out;
}
}
$info = self::str($value);
@ -189,7 +189,7 @@ class ValueInfo {
try {
if (!is_null($dateInFormat)) {
$out = false;
if ($dateInFormat=="microtime") {
if ($dateInFormat === "microtime") {
// PHP is not able to correctly handle the output of microtime() as the input of DateTime::createFromFormat(), so we fudge it to look like a float
if (preg_match("<^0\.\d{6}00 \d+$>", $value)) {
$value = substr($value, 11).".".substr($value, 2, 6);
@ -198,9 +198,9 @@ class ValueInfo {
}
}
$f = isset(self::DATE_FORMATS[$dateInFormat]) ? self::DATE_FORMATS[$dateInFormat][0] : $dateInFormat;
if ($dateInFormat=="iso8601" || $dateInFormat=="iso8601m") {
if ($dateInFormat === "iso8601" || $dateInFormat === "iso8601m") {
// DateTimeImmutable::createFromFormat() doesn't provide one catch-all for ISO 8601 timezone specifiers, so we try all of them till one works
if ($dateInFormat=="iso8601m") {
if ($dateInFormat === "iso8601m") {
$f2 = self::DATE_FORMATS["iso8601"][0];
$zones = [$f."", $f."\Z", $f."P", $f."O", $f2."", $f2."\Z", $f2."P", $f2."O"];
} else {
@ -355,7 +355,7 @@ class ValueInfo {
$out = filter_var($value, \FILTER_VALIDATE_BOOLEAN, \FILTER_NULL_ON_FAILURE);
if (is_null($out) && (ValueInfo::int($value) & ValueInfo::VALID)) {
$out = (int) filter_var($value, \FILTER_VALIDATE_FLOAT);
return ($out==1 || $out==0) ? (bool) $out : $default;
return ($out == 1 || $out == 0) ? (bool) $out : $default;
}
return !is_null($out) ? $out : $default;
}

22
lib/REST.php

@ -76,7 +76,7 @@ class REST {
// fetch the correct handler
$drv = $this->getHandler($class);
// generate a response
if ($req->getMethod()=="HEAD") {
if ($req->getMethod() === "HEAD") {
// if the request is a HEAD request, we act exactly as if it were a GET request, and simply remove the response body later
$res = $drv->dispatch($req->withMethod("GET"));
} else {
@ -108,7 +108,7 @@ class REST {
if (strpos($url, $api['match'])===0) {
// if it matches, perform a more rigorous match and then strip off any defined prefix
$pattern = "<^".preg_quote($api['match'])."([/\?#]|$)>";
if ($url==$api['match'] || in_array(substr($api['match'], -1, 1), ["/", "?", "#"]) || preg_match($pattern, $url)) {
if ($url === $api['match'] || in_array(substr($api['match'], -1, 1), ["/", "?", "#"]) || preg_match($pattern, $url)) {
$target = substr($url, strlen($api['strip']));
} else {
// if the match fails we are not able to handle the request
@ -152,13 +152,13 @@ class REST {
public function normalizeResponse(ResponseInterface $res, RequestInterface $req = null): ResponseInterface {
// if the response code is 401, issue an HTTP authentication challenge
if ($res->getStatusCode()==401) {
if ($res->getStatusCode() == 401) {
$res = $this->challenge($res);
}
// set or clear the Content-Length header field
$body = $res->getBody();
$bodySize = $body->getSize();
if ($bodySize || $res->getStatusCode()==200) {
if ($bodySize || $res->getStatusCode() == 200) {
// if there is a message body or the response is 200, make sure Content-Length is included
$res = $res->withHeader("Content-Length", (string) $bodySize);
} else {
@ -166,7 +166,7 @@ class REST {
$res = $res->withoutHeader("Content-Length");
}
// if the response is to a HEAD request, the body should be omitted
if ($req && $req->getMethod()=="HEAD") {
if ($req && $req->getMethod() === "HEAD") {
$res = new EmptyResponse($res->getStatusCode(), $res->getHeaders());
}
// if an Allow header field is present, normalize it
@ -190,7 +190,7 @@ class REST {
}
public function corsApply(ResponseInterface $res, RequestInterface $req = null): ResponseInterface {
if ($req && $req->getMethod()=="OPTIONS") {
if ($req && $req->getMethod() === "OPTIONS") {
if ($res->hasHeader("Allow")) {
$res = $res->withHeader("Access-Control-Allow-Methods", $res->getHeaderLine("Allow"));
}
@ -211,12 +211,12 @@ class REST {
if ($allowed) {
// continue if the request has exactly one Origin header
$origin = $req->getHeader("Origin");
if (sizeof($origin)==1) {
if (sizeof($origin) == 1) {
// continue if the origin is syntactically valid
$origin = $this->corsNormalizeOrigin($origin[0]);
if ($origin) {
// the special "null" origin should not be matched by the wildcard origin
$null = ($origin=="null");
$null = ($origin === "null");
// pad all strings for simpler comparison
$allowed = " ".$allowed." ";
$denied = " ".$denied." ";
@ -243,7 +243,7 @@ class REST {
public function corsNormalizeOrigin(string $origin, array $ports = null): string {
$origin = trim($origin);
if ($origin=="null") {
if ($origin === "null") {
// if the origin is the special value "null", use it
return "null";
}
@ -259,7 +259,7 @@ class REST {
// if the normalized port contains anything but numbers, or the scheme does not follow the generic URL syntax, the origin is invalid
return "";
}
if ($host[0]=="[") {
if ($host[0] === "[") {
// if the host appears to be an IPv6 address, validate it
$host = rawurldecode(substr($host, 1, strlen($host) - 2));
if (!filter_var($host, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
@ -279,7 +279,7 @@ class REST {
if (strlen($port)) {
$port = (int) substr($port, 1);
$list = array_merge($ports ?? [], self::DEFAULT_PORTS);
if (isset($list[$scheme]) && $port==$list[$scheme]) {
if (isset($list[$scheme]) && $port == $list[$scheme]) {
$port = "";
} else {
$port = ":".$port;

2
lib/REST/AbstractHandler.php

@ -28,7 +28,7 @@ abstract class AbstractHandler implements Handler {
protected function fieldMapTypes(array $data, array $map, string $dateFormat = "sql"): array {
foreach ($map as $key => $type) {
if (array_key_exists($key, $data)) {
if ($type=="datetime" && $dateFormat != "sql") {
if ($type === "datetime" && $dateFormat !== "sql") {
$data[$key] = Date::transform($data[$key], $dateFormat, "sql");
} else {
settype($data[$key], $type);

12
lib/REST/NextCloudNews/V1_2.php

@ -88,7 +88,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
// explode and normalize the URL path
$target = new Target($req->getRequestTarget());
// handle HTTP OPTIONS requests
if ($req->getMethod()=="OPTIONS") {
if ($req->getMethod() === "OPTIONS") {
return $this->handleHTTPOptions((string) $target);
}
// normalize the input
@ -104,7 +104,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
return new EmptyResponse(415, ['Accept' => "application/json"]);
}
$data = @json_decode($data, true);
if (json_last_error() != \JSON_ERROR_NONE) {
if (json_last_error() !== \JSON_ERROR_NONE) {
// if the body could not be parsed as JSON, return "400 Bad Request"
return new EmptyResponse(400);
}
@ -612,7 +612,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
$c = new Context;
$c->edition((int) $url[1]);
// determine whether to mark read or unread
$set = ($url[2]=="read");
$set = ($url[2] === "read");
try {
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
} catch (ExceptionInput $e) {
@ -628,7 +628,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
$c = new Context;
$c->article((int) $url[2]);
// determine whether to mark read or unread
$set = ($url[3]=="star");
$set = ($url[3] ==="star");
try {
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
} catch (ExceptionInput $e) {
@ -641,7 +641,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
// mark an array of articles as read
protected function articleMarkReadMulti(array $url, array $data): ResponseInterface {
// determine whether to mark read or unread
$set = ($url[1]=="read");
$set = ($url[1] ==="read");
// initialize the matching context
$c = new Context;
$c->editions($data['items'] ?? []);
@ -655,7 +655,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
// mark an array of articles as starred
protected function articleMarkStarredMulti(array $url, array $data): ResponseInterface {
// determine whether to mark starred or unstarred
$set = ($url[1]=="star");
$set = ($url[1] ==="star");
// initialize the matching context
$c = new Context;
$c->articles(array_column($data['items'] ?? [], "guidHash"));

14
lib/REST/Target.php

@ -31,9 +31,9 @@ class Target {
} else {
continue;
}
} elseif ($segment==".") {
} elseif ($segment === ".") {
$path[] = "%2E";
} elseif ($segment=="..") {
} elseif ($segment === "..") {
$path[] = "%2E%2E";
} else {
$path[] = rawurlencode(ValueInfo::normalize($segment, ValueInfo::T_STRING));
@ -86,7 +86,7 @@ class Target {
// note that the function assumes any fragment identifier or query has already been stripped off
// syntax-based normalization is applied to the path segments (see RFC 3986 sec. 6.2.2)
// duplicate slashes are NOT collapsed
if (substr($target, 0, 1)=="/") {
if (substr($target, 0, 1) === "/") {
// if the path starts with a slash, strip it off
$target = substr($target, 1);
} else {
@ -96,7 +96,7 @@ class Target {
if (!strlen($target)) {
// if the target is an empty string, this is an index target
$this->index = true;
} elseif (substr($target, -1, 1)=="/") {
} elseif (substr($target, -1, 1) === "/") {
// if the path ends in a slash, this is an index target and the slash should be stripped off
$this->index = true;
$target = substr($target, 0, strlen($target) -1);
@ -107,11 +107,11 @@ class Target {
$out = [];
// resolve relative path segments and decode each retained segment
foreach ($target as $index => $segment) {
if ($segment==".") {
if ($segment === ".") {
// self-referential segments can be ignored
continue;
} elseif ($segment=="..") {
if ($index==0) {
} elseif ($segment === "..") {
if ($index == 0) {
// if the first path segment refers to its parent (which we don't know about) we cannot output a correct path, so we do the best we can
$out[] = null;
} else {

28
lib/REST/TinyTinyRSS/API.php

@ -96,7 +96,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
// reject paths other than the index
return new EmptyResponse(404);
}
if ($req->getMethod()=="OPTIONS") {
if ($req->getMethod() === "OPTIONS") {
// respond to OPTIONS rquests; the response is a fib, as we technically accept any type or method
return new EmptyResponse(204, [
'Allow' => "POST",
@ -107,7 +107,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
if ($data) {
// only JSON entities are allowed, but Content-Type is ignored, as is request method
$data = @json_decode($data, true);
if (json_last_error() != \JSON_ERROR_NONE || !is_array($data)) {
if (json_last_error() !== \JSON_ERROR_NONE || !is_array($data)) {
return new Response(self::FATAL_ERR);
}
try {
@ -125,7 +125,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
// otherwise if HTTP authentication failed or is required, deny access at the HTTP level
return new EmptyResponse(401);
}
if (strtolower((string) $data['op']) != "login") {
if (strtolower((string) $data['op']) !== "login") {
// unless logging in, a session identifier is required
$this->resumeSession((string) $data['sid']);
}
@ -432,7 +432,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
protected function enumerateFeeds(array $subs, $parent = null): array {
$out = [];
foreach ($subs as $s) {
if ($s['folder'] != $parent) {
if ($s['folder'] !== $parent) {
continue;
}
$out[] = [
@ -455,7 +455,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
$out = [];
$feedTotal = 0;
foreach ($cats as $c) {
if ($c['parent'] != $parent || (!$all && !($c['children'] + $c['feeds']))) {
if ($c['parent'] !== $parent || (!$all && !($c['children'] + $c['feeds']))) {
// if the category is the wrong level, or if it's empty and we're not including empties, skip it
continue;
}
@ -546,7 +546,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
// transform the result and return
$out = [];
for ($a = 0; $a < sizeof($cats); $a++) {
if ($cats[$a]['id']==-2) {
if ($cats[$a]['id'] == -2) {
// the Labels category has its unread count as a string in TTRSS (don't ask me why)
settype($cats[$a]['unread'], "string");
}
@ -573,7 +573,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
// retrieve the ID of the existing folder; duplicating a folder silently returns the existing one
$folders = Arsse::$db->folderList(Arsse::$user->id, $in['parent'], false);
foreach ($folders as $folder) {
if ($folder['name']==$in['name']) {
if ($folder['name'] === $in['name']) {
return (string) ((int) $folder['id']); // output is a string in TTRSS
}
}
@ -657,7 +657,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
$subs = [];
$count = 0;
// if the category is the special Labels category or the special All category (which includes labels), add labels to the list
if ($cat==self::CAT_ALL || $cat==self::CAT_LABELS) {
if ($cat == self::CAT_ALL || $cat == self::CAT_LABELS) {
// NOTE: unused labels are not included
foreach (Arsse::$db->labelList($user, false) as $l) {
if ($unread && !$l['unread']) {
@ -672,7 +672,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
}
}
// if the category is the special Special (!) category or the special All category (which includes "special" feeds), add those feeds to the list
if ($cat==self::CAT_ALL || $cat==self::CAT_SPECIAL) {
if ($cat == self::CAT_ALL || $cat == self::CAT_SPECIAL) {
// gather some statistics
$starred = Arsse::$db->articleStarred($user)['unread'];
$fresh = Arsse::$db->articleCount($user, (new Context)->unread(true)->modifiedSince(Date::sub("PT24H")));
@ -754,10 +754,10 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
}
}
try {
if ($cat==self::CAT_NOT_SPECIAL || $cat==self::CAT_ALL) {
if ($cat == self::CAT_NOT_SPECIAL || $cat == self::CAT_ALL) {
// if the "All" or "Not Special" categories were selected this returns all subscription, to any depth
$subs = Arsse::$db->subscriptionList($user, null, true);
} elseif ($cat==self::CAT_UNCATEGORIZED) {
} elseif ($cat == self::CAT_UNCATEGORIZED) {
// the "Uncategorized" special category returns subscriptions in the root, without going deeper
$subs = Arsse::$db->subscriptionList($user, null, false);
} else {
@ -1005,7 +1005,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
// try to rename the folder
Arsse::$db->labelPropertiesSet(Arsse::$user->id, $id, ['name' => $name]);
} catch (ExceptionInput $e) {
if ($e->getCode()==10237) {
if ($e->getCode() == 10237) {
// if the supplied ID was invalid, report an error; other errors are to be ignored
throw new Exception("INCORRECT_USAGE");
}
@ -1352,12 +1352,12 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
$data['skip'] = null;
}
if ($data['include_header']) {
if ($data['skip'] > 0 && $data['order_by'] != "date_reverse") {
if ($data['skip'] > 0 && $data['order_by'] !== "date_reverse") {
// when paginating the header returns the latest ("first") item ID in the full list; we get this ID here
$data['skip'] = 0;
$data['limit'] = 1;
$firstID = ($this->fetchArticles($data, ["id"])->getRow() ?? ['id' => 0])['id'];
} elseif ($data['order_by']=="date_reverse") {
} elseif ($data['order_by'] === "date_reverse") {
// the "date_reverse" sort order doesn't get a first ID because it's meaningless for ascending-order pagination (pages doesn't go stale)
$firstID = 0;
} else {

2
lib/REST/TinyTinyRSS/Icon.php

@ -23,7 +23,7 @@ class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
// otherwise if HTTP authentication failed or did not occur when it is required, deny access at the HTTP level
return new Response(401);
}
if ($req->getMethod() != "GET") {
if ($req->getMethod() !== "GET") {
// only GET requests are allowed
return new Response(405, ['Allow' => "GET"]);
} elseif (!preg_match("<^(\d+)\.ico$>", $req->getRequestTarget(), $match) || !((int) $match[1])) {

6
tests/cases/CLI/TestCLI.php

@ -160,8 +160,8 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("auth")->will($this->returnCallback(function($user, $pass) {
return (
($user == "john.doe@example.com" && $pass == "secret") ||
($user == "jane.doe@example.com" && $pass == "superman")
($user === "john.doe@example.com" && $pass === "secret") ||
($user === "jane.doe@example.com" && $pass === "superman")
);
}));
$this->assertConsole($this->cli, $cmd, $exitStatus, $output);
@ -182,7 +182,7 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
// FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("remove")->will($this->returnCallback(function($user) {
if ($user == "john.doe@example.com") {
if ($user === "john.doe@example.com") {
return true;
}
throw new \JKingWeb\Arsse\User\Exception("doesNotExist");

2
tests/cases/Db/BaseDriver.php

@ -359,7 +359,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
// SQLite is unaffected by the removal of the metadata table; other backends are
// in neither case should a query for the schema version produce an error, however
$this->exec("DROP TABLE IF EXISTS arsse_meta");
$exp = (static::$dbInfo->backend == "SQLite 3") ? 2 : 0;
$exp = (static::$dbInfo->backend === "SQLite 3") ? 2 : 0;
$this->assertSame($exp, $this->drv->schemaVersion());
}

8
tests/cases/Db/BaseStatement.php

@ -58,7 +58,7 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideBindings */
public function testBindATypedValue($value, string $type, string $exp) {
if ($exp=="null") {
if ($exp === "null") {
$query = "SELECT (? is null) as pass";
} else {
$query = "SELECT ($exp = ?) as pass";
@ -75,7 +75,7 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
if (in_array(static::$implementation, ["PostgreSQL", "PDO PostgreSQL"])) {
$this->markTestSkipped("Correct handling of binary data with PostgreSQL is currently unknown");
}
if ($exp=="null") {
if ($exp === "null") {
$query = "SELECT (? is null) as pass";
} else {
$query = "SELECT ($exp = ?) as pass";
@ -275,7 +275,7 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
];
foreach ($tests as $index => list($value, $type, $exp)) {
$t = preg_replace("<^strict >", "", $type);
$exp = ($exp=="null") ? $exp : $this->decorateTypeSyntax($exp, $t);
$exp = ($exp === "null") ? $exp : $this->decorateTypeSyntax($exp, $t);
yield $index => [$value, $type, $exp];
}
}
@ -326,7 +326,7 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
];
foreach ($tests as $index => list($value, $type, $exp)) {
$t = preg_replace("<^strict >", "", $type);
$exp = ($exp=="null") ? $exp : $this->decorateTypeSyntax($exp, $t);
$exp = ($exp === "null") ? $exp : $this->decorateTypeSyntax($exp, $t);
yield $index => [$value, $type, $exp];
}
}

2
tests/cases/Db/MySQLPDO/TestStatement.php

@ -20,7 +20,7 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
protected function decorateTypeSyntax(string $value, string $type): string {
switch ($type) {
case "float":
return (substr($value, -2)==".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
return (substr($value, -2) === ".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
case "string":
if (preg_match("<^char\((\d+)\)$>", $value, $match)) {
return "'".\IntlChar::chr((int) $match[1])."'";

2
tests/cases/Db/PostgreSQL/TestCreation.php

@ -25,7 +25,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest {
$timeout = (string) ceil(Arsse::$conf->dbTimeoutConnect ?? 0);
$postfix = "application_name='arsse' client_encoding='UTF8' connect_timeout='$timeout'";
$act = Driver::makeConnectionString($pdo, $user, $pass, $db, $host, $port, $service);
if ($act==$postfix) {
if ($act === $postfix) {
$this->assertSame($exp, "");
} else {
$test = substr($act, 0, strlen($act) - (strlen($postfix) + 1));

2
tests/cases/Db/PostgreSQL/TestStatement.php

@ -20,7 +20,7 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
protected function decorateTypeSyntax(string $value, string $type): string {
switch ($type) {
case "float":
return (substr($value, -2)==".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
return (substr($value, -2) === ".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
case "string":
if (preg_match("<^char\((\d+)\)$>", $value, $match)) {
return "U&'\\+".str_pad(dechex((int) $match[1]), 6, "0", \STR_PAD_LEFT)."'";

2
tests/cases/Db/PostgreSQLPDO/TestCreation.php

@ -25,7 +25,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest {
$timeout = (string) ceil(Arsse::$conf->dbTimeoutConnect ?? 0);
$postfix = "application_name='arsse' client_encoding='UTF8' connect_timeout='$timeout'";
$act = Driver::makeConnectionString($pdo, $user, $pass, $db, $host, $port, $service);
if ($act==$postfix) {
if ($act === $postfix) {
$this->assertSame($exp, "");
} else {
$test = substr($act, 0, strlen($act) - (strlen($postfix) + 1));

2
tests/cases/Db/PostgreSQLPDO/TestStatement.php

@ -20,7 +20,7 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
protected function decorateTypeSyntax(string $value, string $type): string {
switch ($type) {
case "float":
return (substr($value, -2)==".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
return (substr($value, -2) === ".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
case "string":
if (preg_match("<^char\((\d+)\)$>", $value, $match)) {
return "U&'\\+".str_pad(dechex((int) $match[1]), 6, "0", \STR_PAD_LEFT)."'";

4
tests/cases/Db/SQLite3PDO/TestStatement.php

@ -17,8 +17,8 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
}
protected function decorateTypeSyntax(string $value, string $type): string {
if ($type=="float") {
return (substr($value, -2)==".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
if ($type === "float") {
return (substr($value, -2) === ".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
} else {
return $value;
}

10
tests/cases/REST/TinyTinyRSS/TestAPI.php

@ -350,7 +350,7 @@ LONG_STRING;
'userSessionEnforced' => false,
];
$http401 = new EmptyResponse(401);
if ($type=="login") {
if ($type === "login") {
return [
// conf, user, data, result
[$defaults, null, $johnGood, $johnSess],
@ -474,7 +474,7 @@ LONG_STRING;
[$fullHttp, "", $missingU, $http401],
[$fullHttp, "", $missingP, $http401],
];
} elseif ($type=="isLoggedIn") {
} elseif ($type === "isLoggedIn") {
return [
// conf, user, session, result
[$defaults, null, $sidJohn, $john],
@ -1517,13 +1517,13 @@ LONG_STRING;
protected function filterFolders(int $id = null): array {
return array_filter($this->folders, function($value) use ($id) {
return $value['parent']==$id;
return $value['parent'] == $id;
});
}
protected function filterSubs(int $folder = null): array {
return array_filter($this->subscriptions, function($value) use ($folder) {
return $value['folder']==$folder;
return $value['folder'] == $folder;
});
}
@ -1533,7 +1533,7 @@ LONG_STRING;
$out += $this->reduceFolders($f['id']);
}
$out += array_reduce(array_filter($this->subscriptions, function($value) use ($id) {
return $value['folder']==$id;
return $value['folder'] == $id;
}), function($sum, $value) {
return $sum + $value['unread'];
}, 0);

4
tests/cases/User/TestUser.php

@ -60,7 +60,7 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame($exp, $u->auth($user, $password));
$this->assertNull($u->id);
Phake::verify(Arsse::$db, Phake::times($exp ? 1 : 0))->userExists($user);
Phake::verify(Arsse::$db, Phake::times($exp && $user == "jane.doe@example.com" ? 1 : 0))->userAdd($user, $password);
Phake::verify(Arsse::$db, Phake::times($exp && $user === "jane.doe@example.com" ? 1 : 0))->userAdd($user, $password);
}
public function provideAuthentication() {
@ -274,7 +274,7 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
} finally {
Phake::verify($this->drv, Phake::times($calls))->userPasswordSet;
Phake::verify($u, Phake::times($calls / 2))->generatePassword;
Phake::verify(Arsse::$db, Phake::times($calls==4 ? 2 : 0))->userExists($user);
Phake::verify(Arsse::$db, Phake::times($calls == 4 ? 2 : 0))->userExists($user);
if ($calls == 4) {
Phake::verify(Arsse::$db, Phake::times($exists ? 1 : 0))->userPasswordSet($user, $pass1, null);
Phake::verify(Arsse::$db, Phake::times($exists ? 1 : 0))->userPasswordSet($user, $pass2, null);

8
tests/lib/DatabaseInformation.php

@ -83,7 +83,7 @@ class DatabaseInformation {
} catch (\Throwable $e) {
}
foreach ($sqlite3TableList($db) as $table) {
if ($table == "arsse_meta") {
if ($table === "arsse_meta") {
$db->exec("DELETE FROM $table where key <> 'schema_version'");
} else {
$db->exec("DELETE FROM $table");
@ -137,9 +137,9 @@ class DatabaseInformation {
} catch (\Throwable $e) {
}
foreach ($pgObjectList($db) as $obj) {
if ($obj['type'] != "TABLE") {
if ($obj['type'] !== "TABLE") {
continue;
} elseif ($obj['name'] == "arsse_meta") {
} elseif ($obj['name'] === "arsse_meta") {
$pgExecFunction($db, "DELETE FROM {$obj['name']} where key <> 'schema_version'");
} else {
$pgExecFunction($db, "TRUNCATE TABLE {$obj['name']} restart identity cascade");
@ -181,7 +181,7 @@ class DatabaseInformation {
} catch (\Throwable $e) {
}
foreach ($mysqlTableList($db) as $table) {
if ($table == "arsse_meta") {
if ($table === "arsse_meta") {
$db->query("DELETE FROM $table where `key` <> 'schema_version'");
} else {
$db->query("DELETE FROM $table");

Laddar…
Avbryt
Spara