1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-22 21:22:40 +00:00

Use strict equality when comparing strings

This commit is contained in:
J. King 2019-01-11 10:38:06 -05:00
parent c4a41255b0
commit 81acba90dc
31 changed files with 107 additions and 107 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -135,19 +135,19 @@ class Feed {
// id doesn't exist. // id doesn't exist.
$content = $f->content.$f->enclosureUrl.$f->enclosureType; $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 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 = ""; $f->urlTitleHash = "";
} else { } else {
$f->urlTitleHash = hash('sha256', $f->url.$f->title); $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 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 = ""; $f->urlContentHash = "";
} else { } else {
$f->urlContentHash = hash('sha256', $f->url.$content); $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 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 = ""; $f->titleContentHash = "";
} else { } else {
$f->titleContentHash = hash('sha256', $f->title.$content); $f->titleContentHash = hash('sha256', $f->title.$content);
@ -215,15 +215,15 @@ class Feed {
foreach ($items as $item) { foreach ($items as $item) {
foreach ($out as $index => $check) { foreach ($out as $index => $check) {
// if the two items both have IDs and they differ, they do not match, regardless of hashes // 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; continue;
} }
// if the two items have the same ID or any one hash matches, they are two versions of the same item // if the two items have the same ID or any one hash matches, they are two versions of the same item
if ( if (
($item->id && $check->id && $item->id == $check->id) || ($item->id && $check->id && $item->id === $check->id) ||
($item->urlTitleHash && $item->urlTitleHash == $check->urlTitleHash) || ($item->urlTitleHash && $item->urlTitleHash === $check->urlTitleHash) ||
($item->urlContentHash && $item->urlContentHash == $check->urlContentHash) || ($item->urlContentHash && $item->urlContentHash === $check->urlContentHash) ||
($item->titleContentHash && $item->titleContentHash == $check->titleContentHash) ($item->titleContentHash && $item->titleContentHash === $check->titleContentHash)
) { ) {
if (// because newsfeeds are usually order newest-first, the later item should only be used if... 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 // 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]; $diff = $dates[$a] - $dates[$a+1];
$offsets[] = $this->normalizeDateDiff($diff); $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]); return $now->modify("+".$offsets[0]);
} elseif ($offsets[1]==$offsets[2]) { } elseif ($offsets[1] === $offsets[2]) {
return $now->modify("+".$offsets[1]); return $now->modify("+".$offsets[1]);
} else { } else {
return $now->modify("+ 1 hour"); return $now->modify("+ 1 hour");

View file

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

View file

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

View file

@ -157,7 +157,7 @@ class ValueInfo {
return $out; return $out;
} else { } else {
$out = sprintf("%F", $value); $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); $info = self::str($value);
@ -189,7 +189,7 @@ class ValueInfo {
try { try {
if (!is_null($dateInFormat)) { if (!is_null($dateInFormat)) {
$out = false; $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 // 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)) { if (preg_match("<^0\.\d{6}00 \d+$>", $value)) {
$value = substr($value, 11).".".substr($value, 2, 6); $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; $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 // 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]; $f2 = self::DATE_FORMATS["iso8601"][0];
$zones = [$f."", $f."\Z", $f."P", $f."O", $f2."", $f2."\Z", $f2."P", $f2."O"]; $zones = [$f."", $f."\Z", $f."P", $f."O", $f2."", $f2."\Z", $f2."P", $f2."O"];
} else { } else {

View file

@ -76,7 +76,7 @@ class REST {
// fetch the correct handler // fetch the correct handler
$drv = $this->getHandler($class); $drv = $this->getHandler($class);
// generate a response // 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 // 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")); $res = $drv->dispatch($req->withMethod("GET"));
} else { } else {
@ -108,7 +108,7 @@ class REST {
if (strpos($url, $api['match'])===0) { if (strpos($url, $api['match'])===0) {
// if it matches, perform a more rigorous match and then strip off any defined prefix // if it matches, perform a more rigorous match and then strip off any defined prefix
$pattern = "<^".preg_quote($api['match'])."([/\?#]|$)>"; $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'])); $target = substr($url, strlen($api['strip']));
} else { } else {
// if the match fails we are not able to handle the request // if the match fails we are not able to handle the request
@ -166,7 +166,7 @@ class REST {
$res = $res->withoutHeader("Content-Length"); $res = $res->withoutHeader("Content-Length");
} }
// if the response is to a HEAD request, the body should be omitted // 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()); $res = new EmptyResponse($res->getStatusCode(), $res->getHeaders());
} }
// if an Allow header field is present, normalize it // if an Allow header field is present, normalize it
@ -190,7 +190,7 @@ class REST {
} }
public function corsApply(ResponseInterface $res, RequestInterface $req = null): ResponseInterface { public function corsApply(ResponseInterface $res, RequestInterface $req = null): ResponseInterface {
if ($req && $req->getMethod()=="OPTIONS") { if ($req && $req->getMethod() === "OPTIONS") {
if ($res->hasHeader("Allow")) { if ($res->hasHeader("Allow")) {
$res = $res->withHeader("Access-Control-Allow-Methods", $res->getHeaderLine("Allow")); $res = $res->withHeader("Access-Control-Allow-Methods", $res->getHeaderLine("Allow"));
} }
@ -216,7 +216,7 @@ class REST {
$origin = $this->corsNormalizeOrigin($origin[0]); $origin = $this->corsNormalizeOrigin($origin[0]);
if ($origin) { if ($origin) {
// the special "null" origin should not be matched by the wildcard 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 // pad all strings for simpler comparison
$allowed = " ".$allowed." "; $allowed = " ".$allowed." ";
$denied = " ".$denied." "; $denied = " ".$denied." ";
@ -243,7 +243,7 @@ class REST {
public function corsNormalizeOrigin(string $origin, array $ports = null): string { public function corsNormalizeOrigin(string $origin, array $ports = null): string {
$origin = trim($origin); $origin = trim($origin);
if ($origin=="null") { if ($origin === "null") {
// if the origin is the special value "null", use it // if the origin is the special value "null", use it
return "null"; 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 // if the normalized port contains anything but numbers, or the scheme does not follow the generic URL syntax, the origin is invalid
return ""; return "";
} }
if ($host[0]=="[") { if ($host[0] === "[") {
// if the host appears to be an IPv6 address, validate it // if the host appears to be an IPv6 address, validate it
$host = rawurldecode(substr($host, 1, strlen($host) - 2)); $host = rawurldecode(substr($host, 1, strlen($host) - 2));
if (!filter_var($host, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { if (!filter_var($host, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {

View file

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

View file

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

View file

@ -31,9 +31,9 @@ class Target {
} else { } else {
continue; continue;
} }
} elseif ($segment==".") { } elseif ($segment === ".") {
$path[] = "%2E"; $path[] = "%2E";
} elseif ($segment=="..") { } elseif ($segment === "..") {
$path[] = "%2E%2E"; $path[] = "%2E%2E";
} else { } else {
$path[] = rawurlencode(ValueInfo::normalize($segment, ValueInfo::T_STRING)); $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 // 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) // syntax-based normalization is applied to the path segments (see RFC 3986 sec. 6.2.2)
// duplicate slashes are NOT collapsed // 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 // if the path starts with a slash, strip it off
$target = substr($target, 1); $target = substr($target, 1);
} else { } else {
@ -96,7 +96,7 @@ class Target {
if (!strlen($target)) { if (!strlen($target)) {
// if the target is an empty string, this is an index target // if the target is an empty string, this is an index target
$this->index = true; $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 // if the path ends in a slash, this is an index target and the slash should be stripped off
$this->index = true; $this->index = true;
$target = substr($target, 0, strlen($target) -1); $target = substr($target, 0, strlen($target) -1);
@ -107,10 +107,10 @@ class Target {
$out = []; $out = [];
// resolve relative path segments and decode each retained segment // resolve relative path segments and decode each retained segment
foreach ($target as $index => $segment) { foreach ($target as $index => $segment) {
if ($segment==".") { if ($segment === ".") {
// self-referential segments can be ignored // self-referential segments can be ignored
continue; continue;
} elseif ($segment=="..") { } elseif ($segment === "..") {
if ($index == 0) { 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 // 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; $out[] = null;

View file

@ -96,7 +96,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
// reject paths other than the index // reject paths other than the index
return new EmptyResponse(404); 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 // respond to OPTIONS rquests; the response is a fib, as we technically accept any type or method
return new EmptyResponse(204, [ return new EmptyResponse(204, [
'Allow' => "POST", 'Allow' => "POST",
@ -107,7 +107,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
if ($data) { if ($data) {
// only JSON entities are allowed, but Content-Type is ignored, as is request method // only JSON entities are allowed, but Content-Type is ignored, as is request method
$data = @json_decode($data, true); $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); return new Response(self::FATAL_ERR);
} }
try { 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 // otherwise if HTTP authentication failed or is required, deny access at the HTTP level
return new EmptyResponse(401); return new EmptyResponse(401);
} }
if (strtolower((string) $data['op']) != "login") { if (strtolower((string) $data['op']) !== "login") {
// unless logging in, a session identifier is required // unless logging in, a session identifier is required
$this->resumeSession((string) $data['sid']); $this->resumeSession((string) $data['sid']);
} }
@ -432,7 +432,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
protected function enumerateFeeds(array $subs, $parent = null): array { protected function enumerateFeeds(array $subs, $parent = null): array {
$out = []; $out = [];
foreach ($subs as $s) { foreach ($subs as $s) {
if ($s['folder'] != $parent) { if ($s['folder'] !== $parent) {
continue; continue;
} }
$out[] = [ $out[] = [
@ -455,7 +455,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
$out = []; $out = [];
$feedTotal = 0; $feedTotal = 0;
foreach ($cats as $c) { 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 // if the category is the wrong level, or if it's empty and we're not including empties, skip it
continue; continue;
} }
@ -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 // 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); $folders = Arsse::$db->folderList(Arsse::$user->id, $in['parent'], false);
foreach ($folders as $folder) { 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 return (string) ((int) $folder['id']); // output is a string in TTRSS
} }
} }
@ -1352,12 +1352,12 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
$data['skip'] = null; $data['skip'] = null;
} }
if ($data['include_header']) { 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 // when paginating the header returns the latest ("first") item ID in the full list; we get this ID here
$data['skip'] = 0; $data['skip'] = 0;
$data['limit'] = 1; $data['limit'] = 1;
$firstID = ($this->fetchArticles($data, ["id"])->getRow() ?? ['id' => 0])['id']; $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) // 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; $firstID = 0;
} else { } else {

View file

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

View file

@ -160,8 +160,8 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
Arsse::$user = $this->createMock(User::class); Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("auth")->will($this->returnCallback(function($user, $pass) { Arsse::$user->method("auth")->will($this->returnCallback(function($user, $pass) {
return ( return (
($user == "john.doe@example.com" && $pass == "secret") || ($user === "john.doe@example.com" && $pass === "secret") ||
($user == "jane.doe@example.com" && $pass == "superman") ($user === "jane.doe@example.com" && $pass === "superman")
); );
})); }));
$this->assertConsole($this->cli, $cmd, $exitStatus, $output); $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 // 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 = $this->createMock(User::class);
Arsse::$user->method("remove")->will($this->returnCallback(function($user) { Arsse::$user->method("remove")->will($this->returnCallback(function($user) {
if ($user == "john.doe@example.com") { if ($user === "john.doe@example.com") {
return true; return true;
} }
throw new \JKingWeb\Arsse\User\Exception("doesNotExist"); throw new \JKingWeb\Arsse\User\Exception("doesNotExist");

View file

@ -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 // 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 // in neither case should a query for the schema version produce an error, however
$this->exec("DROP TABLE IF EXISTS arsse_meta"); $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()); $this->assertSame($exp, $this->drv->schemaVersion());
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -17,8 +17,8 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
} }
protected function decorateTypeSyntax(string $value, string $type): string { protected function decorateTypeSyntax(string $value, string $type): string {
if ($type=="float") { if ($type === "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'";
} else { } else {
return $value; return $value;
} }

View file

@ -350,7 +350,7 @@ LONG_STRING;
'userSessionEnforced' => false, 'userSessionEnforced' => false,
]; ];
$http401 = new EmptyResponse(401); $http401 = new EmptyResponse(401);
if ($type=="login") { if ($type === "login") {
return [ return [
// conf, user, data, result // conf, user, data, result
[$defaults, null, $johnGood, $johnSess], [$defaults, null, $johnGood, $johnSess],
@ -474,7 +474,7 @@ LONG_STRING;
[$fullHttp, "", $missingU, $http401], [$fullHttp, "", $missingU, $http401],
[$fullHttp, "", $missingP, $http401], [$fullHttp, "", $missingP, $http401],
]; ];
} elseif ($type=="isLoggedIn") { } elseif ($type === "isLoggedIn") {
return [ return [
// conf, user, session, result // conf, user, session, result
[$defaults, null, $sidJohn, $john], [$defaults, null, $sidJohn, $john],

View file

@ -60,7 +60,7 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame($exp, $u->auth($user, $password)); $this->assertSame($exp, $u->auth($user, $password));
$this->assertNull($u->id); $this->assertNull($u->id);
Phake::verify(Arsse::$db, Phake::times($exp ? 1 : 0))->userExists($user); 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() { public function provideAuthentication() {

View file

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