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:
parent
c4a41255b0
commit
81acba90dc
31 changed files with 107 additions and 107 deletions
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,7 +364,7 @@ class Database {
|
||||||
$parent = (int) $parent;
|
$parent = (int) $parent;
|
||||||
}
|
}
|
||||||
// if the target parent is the folder itself, this is a circular dependence
|
// 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);
|
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);
|
// make sure both that the prospective parent exists, and that the it is not one of its children (a circular dependence);
|
||||||
|
|
|
@ -131,7 +131,7 @@ abstract class AbstractDriver implements Driver {
|
||||||
default:
|
default:
|
||||||
throw new Exception("savepointStatusUnknown", $this->transStatus[$index]); // @codeCoverageIgnore
|
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
|
// 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) {
|
while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) {
|
||||||
array_pop($this->transStatus);
|
array_pop($this->transStatus);
|
||||||
|
@ -185,7 +185,7 @@ abstract class AbstractDriver implements Driver {
|
||||||
default:
|
default:
|
||||||
throw new Exception("savepointStatusUnknown", $this->transStatus[$index]); // @codeCoverageIgnore
|
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) {
|
while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) {
|
||||||
array_pop($this->transStatus);
|
array_pop($this->transStatus);
|
||||||
$this->transDepth--;
|
$this->transDepth--;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
20
lib/Feed.php
20
lib/Feed.php
|
@ -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");
|
||||||
|
|
18
lib/Lang.php
18
lib/Lang.php
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
@ -355,7 +355,7 @@ class ValueInfo {
|
||||||
$out = filter_var($value, \FILTER_VALIDATE_BOOLEAN, \FILTER_NULL_ON_FAILURE);
|
$out = filter_var($value, \FILTER_VALIDATE_BOOLEAN, \FILTER_NULL_ON_FAILURE);
|
||||||
if (is_null($out) && (ValueInfo::int($value) & ValueInfo::VALID)) {
|
if (is_null($out) && (ValueInfo::int($value) & ValueInfo::VALID)) {
|
||||||
$out = (int) filter_var($value, \FILTER_VALIDATE_FLOAT);
|
$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;
|
return !is_null($out) ? $out : $default;
|
||||||
}
|
}
|
||||||
|
|
22
lib/REST.php
22
lib/REST.php
|
@ -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
|
||||||
|
@ -152,13 +152,13 @@ class REST {
|
||||||
|
|
||||||
public function normalizeResponse(ResponseInterface $res, RequestInterface $req = null): ResponseInterface {
|
public function normalizeResponse(ResponseInterface $res, RequestInterface $req = null): ResponseInterface {
|
||||||
// if the response code is 401, issue an HTTP authentication challenge
|
// if the response code is 401, issue an HTTP authentication challenge
|
||||||
if ($res->getStatusCode()==401) {
|
if ($res->getStatusCode() == 401) {
|
||||||
$res = $this->challenge($res);
|
$res = $this->challenge($res);
|
||||||
}
|
}
|
||||||
// set or clear the Content-Length header field
|
// set or clear the Content-Length header field
|
||||||
$body = $res->getBody();
|
$body = $res->getBody();
|
||||||
$bodySize = $body->getSize();
|
$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
|
// if there is a message body or the response is 200, make sure Content-Length is included
|
||||||
$res = $res->withHeader("Content-Length", (string) $bodySize);
|
$res = $res->withHeader("Content-Length", (string) $bodySize);
|
||||||
} else {
|
} else {
|
||||||
|
@ -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"));
|
||||||
}
|
}
|
||||||
|
@ -211,12 +211,12 @@ class REST {
|
||||||
if ($allowed) {
|
if ($allowed) {
|
||||||
// continue if the request has exactly one Origin header
|
// continue if the request has exactly one Origin header
|
||||||
$origin = $req->getHeader("Origin");
|
$origin = $req->getHeader("Origin");
|
||||||
if (sizeof($origin)==1) {
|
if (sizeof($origin) == 1) {
|
||||||
// continue if the origin is syntactically valid
|
// continue if the origin is syntactically valid
|
||||||
$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)) {
|
||||||
|
@ -279,7 +279,7 @@ class REST {
|
||||||
if (strlen($port)) {
|
if (strlen($port)) {
|
||||||
$port = (int) substr($port, 1);
|
$port = (int) substr($port, 1);
|
||||||
$list = array_merge($ports ?? [], self::DEFAULT_PORTS);
|
$list = array_merge($ports ?? [], self::DEFAULT_PORTS);
|
||||||
if (isset($list[$scheme]) && $port==$list[$scheme]) {
|
if (isset($list[$scheme]) && $port == $list[$scheme]) {
|
||||||
$port = "";
|
$port = "";
|
||||||
} else {
|
} else {
|
||||||
$port = ":".$port;
|
$port = ":".$port;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
|
@ -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,11 +107,11 @@ 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;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -546,7 +546,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
// transform the result and return
|
// transform the result and return
|
||||||
$out = [];
|
$out = [];
|
||||||
for ($a = 0; $a < sizeof($cats); $a++) {
|
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)
|
// the Labels category has its unread count as a string in TTRSS (don't ask me why)
|
||||||
settype($cats[$a]['unread'], "string");
|
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
|
// 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,7 +657,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
$subs = [];
|
$subs = [];
|
||||||
$count = 0;
|
$count = 0;
|
||||||
// if the category is the special Labels category or the special All category (which includes labels), add labels to the list
|
// 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
|
// NOTE: unused labels are not included
|
||||||
foreach (Arsse::$db->labelList($user, false) as $l) {
|
foreach (Arsse::$db->labelList($user, false) as $l) {
|
||||||
if ($unread && !$l['unread']) {
|
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 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
|
// gather some statistics
|
||||||
$starred = Arsse::$db->articleStarred($user)['unread'];
|
$starred = Arsse::$db->articleStarred($user)['unread'];
|
||||||
$fresh = Arsse::$db->articleCount($user, (new Context)->unread(true)->modifiedSince(Date::sub("PT24H")));
|
$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 {
|
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
|
// if the "All" or "Not Special" categories were selected this returns all subscription, to any depth
|
||||||
$subs = Arsse::$db->subscriptionList($user, null, true);
|
$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
|
// the "Uncategorized" special category returns subscriptions in the root, without going deeper
|
||||||
$subs = Arsse::$db->subscriptionList($user, null, false);
|
$subs = Arsse::$db->subscriptionList($user, null, false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1005,7 +1005,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
// try to rename the folder
|
// try to rename the folder
|
||||||
Arsse::$db->labelPropertiesSet(Arsse::$user->id, $id, ['name' => $name]);
|
Arsse::$db->labelPropertiesSet(Arsse::$user->id, $id, ['name' => $name]);
|
||||||
} catch (ExceptionInput $e) {
|
} 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
|
// if the supplied ID was invalid, report an error; other errors are to be ignored
|
||||||
throw new Exception("INCORRECT_USAGE");
|
throw new Exception("INCORRECT_USAGE");
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
|
|
@ -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])) {
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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])."'";
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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)."'";
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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)."'";
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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],
|
||||||
|
@ -1517,13 +1517,13 @@ LONG_STRING;
|
||||||
|
|
||||||
protected function filterFolders(int $id = null): array {
|
protected function filterFolders(int $id = null): array {
|
||||||
return array_filter($this->folders, function($value) use ($id) {
|
return array_filter($this->folders, function($value) use ($id) {
|
||||||
return $value['parent']==$id;
|
return $value['parent'] == $id;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function filterSubs(int $folder = null): array {
|
protected function filterSubs(int $folder = null): array {
|
||||||
return array_filter($this->subscriptions, function($value) use ($folder) {
|
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 += $this->reduceFolders($f['id']);
|
||||||
}
|
}
|
||||||
$out += array_reduce(array_filter($this->subscriptions, function($value) use ($id) {
|
$out += array_reduce(array_filter($this->subscriptions, function($value) use ($id) {
|
||||||
return $value['folder']==$id;
|
return $value['folder'] == $id;
|
||||||
}), function($sum, $value) {
|
}), function($sum, $value) {
|
||||||
return $sum + $value['unread'];
|
return $sum + $value['unread'];
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
|
@ -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() {
|
||||||
|
@ -274,7 +274,7 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
} finally {
|
} finally {
|
||||||
Phake::verify($this->drv, Phake::times($calls))->userPasswordSet;
|
Phake::verify($this->drv, Phake::times($calls))->userPasswordSet;
|
||||||
Phake::verify($u, Phake::times($calls / 2))->generatePassword;
|
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) {
|
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, $pass1, null);
|
||||||
Phake::verify(Arsse::$db, Phake::times($exists ? 1 : 0))->userPasswordSet($user, $pass2, null);
|
Phake::verify(Arsse::$db, Phake::times($exists ? 1 : 0))->userPasswordSet($user, $pass2, null);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Reference in a new issue