From f7e50fe95d1535f83d16edd08730841d602c8f92 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Tue, 29 Aug 2017 10:50:31 -0400 Subject: [PATCH] Passed code through linter --- .php_cs.dist | 25 ++ arsse.php | 7 +- lib/AbstractException.php | 7 +- lib/Arsse.php | 4 +- lib/CLI.php | 34 +-- lib/Conf.php | 41 +-- lib/Conf/Exception.php | 2 +- lib/Database.php | 289 +++++++++--------- lib/Db/AbstractDriver.php | 44 +-- lib/Db/AbstractStatement.php | 32 +- lib/Db/Driver.php | 26 +- lib/Db/Exception.php | 2 +- lib/Db/ExceptionInput.php | 2 +- lib/Db/ExceptionSavepoint.php | 2 +- lib/Db/ExceptionTimeout.php | 2 +- lib/Db/Result.php | 22 +- lib/Db/SQLite3/Driver.php | 51 ++-- lib/Db/SQLite3/ExceptionBuilder.php | 7 +- lib/Db/SQLite3/Result.php | 11 +- lib/Db/SQLite3/Statement.php | 22 +- lib/Db/Statement.php | 10 +- lib/Db/Transaction.php | 18 +- lib/Exception.php | 2 +- lib/ExceptionFatal.php | 2 +- lib/Feed.php | 121 ++++---- lib/Feed/Exception.php | 2 +- lib/Lang.php | 84 ++--- lib/Lang/Exception.php | 2 +- lib/Misc/Context.php | 51 ++-- lib/Misc/Date.php | 35 ++- lib/Misc/Query.php | 58 ++-- lib/REST.php | 20 +- lib/REST/AbstractHandler.php | 46 +-- lib/REST/Exception.php | 2 +- lib/REST/Exception405.php | 2 +- lib/REST/Exception501.php | 2 +- lib/REST/Handler.php | 6 +- lib/REST/NextCloudNews/V1_2.php | 148 ++++----- lib/REST/NextCloudNews/Versions.php | 11 +- lib/REST/Request.php | 32 +- lib/REST/Response.php | 21 +- lib/Service.php | 33 +- lib/Service/Curl/Driver.php | 19 +- lib/Service/Driver.php | 12 +- lib/Service/Forking/Driver.php | 19 +- lib/Service/Internal/Driver.php | 17 +- lib/User.php | 147 ++++----- lib/User/Driver.php | 30 +- lib/User/Exception.php | 2 +- lib/User/ExceptionAuthz.php | 2 +- lib/User/ExceptionNotImplemented.php | 2 +- lib/User/Internal/Driver.php | 8 +- lib/User/Internal/InternalFunctions.php | 27 +- tests/Conf/TestConf.php | 37 +-- .../Database/TestDatabaseArticleSQLite3.php | 2 +- .../Database/TestDatabaseCleanupSQLite3.php | 2 +- .../Database/TestDatabaseFeedSQLite3.php | 2 +- .../Database/TestDatabaseFolderSQLite3.php | 2 +- .../Database/TestDatabaseMetaSQLite3.php | 2 +- .../TestDatabaseMiscellanySQLite3.php | 2 +- .../TestDatabaseSubscriptionSQLite3.php | 2 +- .../Database/TestDatabaseUserSQLite3.php | 2 +- .../SQLite3/TestDbDriverCreationSQLite3.php | 45 +-- tests/Db/SQLite3/TestDbDriverSQLite3.php | 74 ++--- tests/Db/SQLite3/TestDbResultSQLite3.php | 31 +- tests/Db/SQLite3/TestDbStatementSQLite3.php | 30 +- tests/Db/SQLite3/TestDbUpdateSQLite3.php | 36 +-- tests/Db/TestTransaction.php | 11 +- tests/Exception/TestException.php | 18 +- tests/Feed/TestFeed.php | 44 +-- tests/Feed/TestFeedFetching.php | 28 +- tests/Lang/TestLang.php | 14 +- tests/Lang/TestLangErrors.php | 23 +- tests/Lang/testLangComplex.php | 27 +- tests/Misc/TestContext.php | 22 +- tests/REST/NextCloudNews/TestNCNV1_2.php | 85 +++--- .../NextCloudNews/TestNCNVersionDiscovery.php | 11 +- tests/Service/TestService.php | 19 +- tests/User/TestAuthorization.php | 137 ++++----- tests/User/TestUserInternalDriver.php | 2 +- tests/User/TestUserMockExternal.php | 2 +- tests/User/TestUserMockInternal.php | 2 +- tests/docroot/Feed/Caching/200Future.php | 2 +- tests/docroot/Feed/Caching/200Multiple.php | 2 +- tests/docroot/Feed/Caching/200None.php | 2 +- tests/docroot/Feed/Caching/200Past.php | 2 +- tests/docroot/Feed/Caching/200PubDateOnly.php | 2 +- tests/docroot/Feed/Caching/200UpdateDate.php | 2 +- tests/docroot/Feed/Caching/304ETagOnly.php | 2 +- tests/docroot/Feed/Caching/304LastModOnly.php | 2 +- tests/docroot/Feed/Caching/304None.php | 2 +- tests/docroot/Feed/Caching/304Random.php | 4 +- .../Feed/Deduplication/Hashes-Dates1.php | 2 +- .../Feed/Deduplication/Hashes-Dates2.php | 2 +- .../Feed/Deduplication/Hashes-Dates3.php | 2 +- tests/docroot/Feed/Deduplication/Hashes.php | 2 +- tests/docroot/Feed/Deduplication/ID-Dates.php | 2 +- .../Feed/Deduplication/IdenticalHashes.php | 2 +- .../Feed/Deduplication/Permalink-Dates.php | 2 +- tests/docroot/Feed/Fetching/EndlessLoop.php | 2 +- tests/docroot/Feed/Fetching/Error.php | 2 +- tests/docroot/Feed/Fetching/Timeout.php | 2 +- tests/docroot/Feed/Fetching/TooLarge.php | 4 +- tests/docroot/Feed/Matching/1.php | 2 +- tests/docroot/Feed/Matching/2.php | 2 +- tests/docroot/Feed/Matching/3.php | 2 +- tests/docroot/Feed/Matching/4.php | 2 +- tests/docroot/Feed/Matching/5.php | 2 +- tests/docroot/Feed/NextFetch/1h.php | 2 +- tests/docroot/Feed/NextFetch/3-36h.php | 2 +- tests/docroot/Feed/NextFetch/30m.php | 2 +- tests/docroot/Feed/NextFetch/36h.php | 2 +- tests/docroot/Feed/NextFetch/3h.php | 2 +- tests/docroot/Feed/NextFetch/Fallback.php | 2 +- tests/docroot/Feed/NextFetch/NotModified.php | 4 +- tests/docroot/Feed/Parsing/Malformed.php | 2 +- tests/docroot/Feed/Parsing/Unsupported.php | 2 +- tests/docroot/Feed/Parsing/Valid.php | 2 +- tests/docroot/Feed/Parsing/XEEAttack.php | 2 +- tests/docroot/Feed/Parsing/XXEAttack.php | 2 +- tests/docroot/Feed/Scraping/Document.php | 2 +- tests/docroot/Feed/Scraping/Feed.php | 2 +- tests/docroot/IsUp.php | 2 +- tests/lib/AbstractTest.php | 18 +- tests/lib/Database.php | 2 +- tests/lib/Database/DriverSQLite3.php | 9 +- tests/lib/Database/SeriesArticle.php | 101 +++--- tests/lib/Database/SeriesCleanup.php | 32 +- tests/lib/Database/SeriesFeed.php | 31 +- tests/lib/Database/SeriesFolder.php | 75 ++--- tests/lib/Database/SeriesMeta.php | 15 +- tests/lib/Database/SeriesMiscellany.php | 10 +- tests/lib/Database/SeriesSubscription.php | 65 ++-- tests/lib/Database/SeriesUser.php | 67 ++-- tests/lib/Database/Setup.php | 53 ++-- tests/lib/Db/BindingTests.php | 33 +- tests/lib/Lang/Setup.php | 17 +- tests/lib/Lang/TestLang.php | 4 +- tests/lib/Result.php | 4 +- tests/lib/User/CommonTests.php | 56 ++-- tests/lib/User/Database.php | 110 ++++--- tests/lib/User/DriverExternalMock.php | 82 +++-- tests/lib/User/DriverInternalMock.php | 26 +- tests/lib/User/DriverSkeleton.php | 26 +- tests/server.php | 21 +- 145 files changed, 1728 insertions(+), 1556 deletions(-) create mode 100644 .php_cs.dist diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000..dde860e --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,25 @@ + true, + 'braces' => ['position_after_functions_and_oop_constructs' => "same"], +]; + +$finder = \PhpCsFixer\Finder::create(); +foreach ($paths as $path) { + if (is_file($path)) { + $finder = $finder->path($path); + } else { + $finder = $finder->in($path); + } +} +return \PhpCsFixer\Config::create()->setRules($rules)->setFinder($finder); \ No newline at end of file diff --git a/arsse.php b/arsse.php index 5ff4623..8634bf5 100644 --- a/arsse.php +++ b/arsse.php @@ -1,8 +1,9 @@ importFile(BASE."config.php"); } // handle Web requests (new REST)->dispatch()->output(); -} \ No newline at end of file +} diff --git a/lib/AbstractException.php b/lib/AbstractException.php index e726113..034254c 100644 --- a/lib/AbstractException.php +++ b/lib/AbstractException.php @@ -3,7 +3,6 @@ declare(strict_types=1); namespace JKingWeb\Arsse; abstract class AbstractException extends \Exception { - const CODES = [ "Exception.uncoded" => -1, "Exception.unknown" => 10000, @@ -71,13 +70,13 @@ abstract class AbstractException extends \Exception { ]; public function __construct(string $msgID = "", $vars = null, \Throwable $e = null) { - if($msgID=="") { + if ($msgID=="") { $msg = "Exception.unknown"; $code = 10000; } else { $class = get_called_class(); $codeID = str_replace("\\", "/", str_replace(NS_BASE, "", $class)).".$msgID"; - if(!array_key_exists($codeID, self::CODES)) { + if (!array_key_exists($codeID, self::CODES)) { throw new Exception("uncoded", $codeID); } else { $code = self::CODES[$codeID]; @@ -87,4 +86,4 @@ abstract class AbstractException extends \Exception { } parent::__construct($msg, $code, $e); } -} \ No newline at end of file +} diff --git a/lib/Arsse.php b/lib/Arsse.php index 214fa12..2475ed6 100644 --- a/lib/Arsse.php +++ b/lib/Arsse.php @@ -12,11 +12,11 @@ class Arsse { /** @var User */ public static $user; - static function load(Conf $conf) { + public static function load(Conf $conf) { static::$lang = new Lang(); static::$conf = $conf; static::$lang->set($conf->lang); static::$db = new Database(); static::$user = new User(); } -} \ No newline at end of file +} diff --git a/lib/CLI.php b/lib/CLI.php index 895fc36..b62e4f4 100644 --- a/lib/CLI.php +++ b/lib/CLI.php @@ -22,8 +22,8 @@ configuration to a sample file. USAGE_TEXT; } - function __construct(array $argv = null) { - if(is_null($argv)) { + public function __construct(array $argv = null) { + if (is_null($argv)) { $argv = array_slice($_SERVER['argv'], 1); } $this->args = \Docopt::handle($this->usage(), [ @@ -36,7 +36,7 @@ USAGE_TEXT; protected function loadConf(): bool { // FIXME: this should be a method of the Conf class Arsse::load(new Conf()); - if(file_exists(BASE."config.php")) { + if (file_exists(BASE."config.php")) { Arsse::$conf->importFile(BASE."config.php"); } // command-line operations will never respect authorization @@ -44,52 +44,52 @@ USAGE_TEXT; return true; } - function dispatch(array $args = null): int { + public function dispatch(array $args = null): int { // act on command line - if(is_null($args)) { + if (is_null($args)) { $args = $this->args; } - if($this->command("daemon", $args)) { + if ($this->command("daemon", $args)) { $this->loadConf(); return $this->daemon(); - } else if($this->command("feed refresh", $args)) { + } elseif ($this->command("feed refresh", $args)) { $this->loadConf(); return $this->feedRefresh((int) $args['']); - } else if($this->command("conf save-defaults", $args)) { + } elseif ($this->command("conf save-defaults", $args)) { return $this->confSaveDefaults($args['']); - } else if($this->command("user add", $args)) { + } elseif ($this->command("user add", $args)) { $this->loadConf(); return $this->userAdd($args[''], $args['']); } } protected function command($cmd, $args): bool { - foreach(explode(" ", $cmd) as $part) { - if(!$args[$part]) { + foreach (explode(" ", $cmd) as $part) { + if (!$args[$part]) { return false; } } return true; } - function daemon(bool $loop = true): int { + public function daemon(bool $loop = true): int { (new Service)->watch($loop); return 0; // FIXME: should return the exception code of thrown exceptions } - function feedRefresh(int $id): int { + public function feedRefresh(int $id): int { return (int) !Arsse::$db->feedUpdate($id); // FIXME: exception error codes should be returned here } - function confSaveDefaults(string $file): int { + public function confSaveDefaults(string $file): int { return (int) !(new Conf)->exportFile($file, true); } - function userAdd(string $user, string $password = null): int { + public function userAdd(string $user, string $password = null): int { $passwd = Arsse::$user->add($user, $password); - if(is_null($password)) { + if (is_null($password)) { echo $passwd; } return 0; } -} \ No newline at end of file +} diff --git a/lib/Conf.php b/lib/Conf.php index a71d49c..7b4ad3c 100644 --- a/lib/Conf.php +++ b/lib/Conf.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse; /** Class for loading, saving, and querying configuration - * + * * The Conf class serves both as a means of importing and querying configuration information, as well as a source for default parameters when a configuration file does not specify a value. * All public properties are configuration parameters that may be set by the server administrator. */ class Conf { @@ -57,50 +57,50 @@ class Conf { public $purgeFeeds = "PT24H"; /** @var string When to delete an unstarred article in the database after it has been marked read by all users, as an ISO 8601 duration (default: 7 days; empty string for never) * @see https://en.wikipedia.org/wiki/ISO_8601#Durations */ - public $purgeArticlesRead = "P7D"; + public $purgeArticlesRead = "P7D"; /** @var string When to delete an unstarred article in the database regardless of its read state, as an ISO 8601 duration (default: 21 days; empty string for never) * @see https://en.wikipedia.org/wiki/ISO_8601#Durations */ - public $purgeArticlesUnread = "P21D"; + public $purgeArticlesUnread = "P21D"; /** Creates a new configuration object * @param string $import_file Optional file to read configuration data from * @see self::importFile() */ public function __construct(string $import_file = "") { - if($import_file != "") { + if ($import_file != "") { $this->importFile($import_file); } } - /** Layers configuration data from a file into an existing object + /** Layers configuration data from a file into an existing object * * The file must be a PHP script which return an array with keys that match the properties of the Conf class. Malformed files will throw an exception; unknown keys are silently ignored. Files may be imported is succession, though this is not currently used. * @param string $file Full path and file name for the file to import */ public function importFile(string $file): self { - if(!file_exists($file)) { + if (!file_exists($file)) { throw new Conf\Exception("fileMissing", $file); - } else if(!is_readable($file)) { + } elseif (!is_readable($file)) { throw new Conf\Exception("fileUnreadable", $file); } try { ob_start(); $arr = (@include $file); - } catch(\Throwable $e) { + } catch (\Throwable $e) { $arr = null; } finally { ob_end_clean(); } - if(!is_array($arr)) { + if (!is_array($arr)) { throw new Conf\Exception("fileCorrupt", $file); } return $this->import($arr); } - /** Layers configuration data from an associative array into an existing object + /** Layers configuration data from an associative array into an existing object * * The input array must have keys that match the properties of the Conf class; unknown keys are silently ignored. Arrays may be imported is succession, though this is not currently used. * @param mixed[] $arr Array of configuration parameters to export */ public function import(array $arr): self { - foreach($arr as $key => $value) { + foreach ($arr as $key => $value) { $this->$key = $value; } return $this; @@ -112,13 +112,13 @@ class Conf { $ref = new self; $out = []; $conf = new \ReflectionObject($this); - foreach($conf->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) { + foreach ($conf->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) { $name = $prop->name; // add the property to the output if the value is scalar and either: // 1. full output has been requested // 2. the property is not defined in the class // 3. it differs from the default - if(is_scalar($this->$name) && ($full || !$prop->isDefault() || $this->$name !== $ref->$name)) { + if (is_scalar($this->$name) && ($full || !$prop->isDefault() || $this->$name !== $ref->$name)) { $out[$name] = $this->$name; } } @@ -132,31 +132,32 @@ class Conf { $arr = $this->export($full); $conf = new \ReflectionObject($this); $out = " $value) { + foreach ($arr as $prop => $value) { $match = null; $doc = $comment = ""; // retrieve the property's docblock, if it exists try { $doc = (new \ReflectionProperty(self::class, $prop))->getDocComment(); - } catch(\ReflectionException $e) {} - if($doc) { + } catch (\ReflectionException $e) { + } + if ($doc) { // parse the docblock to extract the property description - if(preg_match("<@var\s+\S+\s+(.+?)(?:\s*\*/)?$>m", $doc, $match)) { + if (preg_match("<@var\s+\S+\s+(.+?)(?:\s*\*/)?$>m", $doc, $match)) { $comment = $match[1]; } } // append the docblock description if there is one, or an empty comment otherwise $out .= " // ".$comment.PHP_EOL; // append the property and an export of its value to the output - $out .= " ".var_export($prop, true)." => ".var_export($value,true).",".PHP_EOL; + $out .= " ".var_export($prop, true)." => ".var_export($value, true).",".PHP_EOL; } $out .= "];".PHP_EOL; // write the configuration representation to the requested file - if(!@file_put_contents($file,$out)) { + if (!@file_put_contents($file, $out)) { // if it fails throw an exception $err = file_exists($file) ? "fileUnwritable" : "fileUncreatable"; throw new Conf\Exception($err, $file); } return true; } -} \ No newline at end of file +} diff --git a/lib/Conf/Exception.php b/lib/Conf/Exception.php index 9e2342a..452a2d9 100644 --- a/lib/Conf/Exception.php +++ b/lib/Conf/Exception.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Conf; class Exception extends \JKingWeb\Arsse\AbstractException { -} \ No newline at end of file +} diff --git a/lib/Database.php b/lib/Database.php index a3223c3..4983da3 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -1,6 +1,7 @@ dbDriver; $this->db = new $driver(); $ver = $this->db->schemaVersion(); - if($initialize && $ver < self::SCHEMA_VERSION) { + if ($initialize && $ver < self::SCHEMA_VERSION) { $this->db->schemaUpdate(self::SCHEMA_VERSION); } } @@ -25,11 +26,11 @@ class Database { return debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function']; } - static public function driverList(): array { + public static function driverList(): array { $sep = \DIRECTORY_SEPARATOR; $path = __DIR__.$sep."Db".$sep; $classes = []; - foreach(glob($path."*".$sep."Driver.php") as $file) { + foreach (glob($path."*".$sep."Driver.php") as $file) { $name = basename(dirname($file)); $class = NS_BASE."Db\\$name\\Driver"; $classes[$class] = $class::driverName(); @@ -42,7 +43,7 @@ class Database { } public function driverSchemaUpdate(): bool { - if($this->db->schemaVersion() < self::SCHEMA_VERSION) { + if ($this->db->schemaVersion() < self::SCHEMA_VERSION) { return $this->db->schemaUpdate(self::SCHEMA_VERSION); } return false; @@ -54,8 +55,8 @@ class Database { [], // binding types [], // binding values ]; - foreach($valid as $prop => $type) { - if(!array_key_exists($prop, $props)) { + foreach ($valid as $prop => $type) { + if (!array_key_exists($prop, $props)) { continue; } $out[0][] = "$prop = ?"; @@ -72,9 +73,9 @@ class Database { [], // binding types ]; // the query clause is just a series of question marks separated by commas - $out[0] = implode(",",array_fill(0,sizeof($values),"?")); + $out[0] = implode(",", array_fill(0, sizeof($values), "?")); // the binding types are just a repetition of the supplied type - $out[1] = array_fill(0,sizeof($values),$type); + $out[1] = array_fill(0, sizeof($values), $type); return $out; } @@ -88,7 +89,7 @@ class Database { public function metaSet(string $key, $value, string $type = "str"): bool { $out = $this->db->prepare("UPDATE arsse_meta set value = ? where key is ?", $type, "str")->run($value, $key)->changes(); - if(!$out) { + if (!$out) { $out = $this->db->prepare("INSERT INTO arsse_meta(key,value) values(?,?)", "str", $type)->run($key, $value)->changes(); } return (bool) $out; @@ -99,23 +100,23 @@ class Database { } public function userExists(string $user): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } return (bool) $this->db->prepare("SELECT count(*) from arsse_users where id is ?", "str")->run($user)->getValue(); } public function userAdd(string $user, string $password = null): string { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - } else if($this->userExists($user)) { + } elseif ($this->userExists($user)) { throw new User\Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]); } - if($password===null) { + if ($password===null) { $password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); } $hash = ""; - if(strlen($password) > 0) { + if (strlen($password) > 0) { $hash = password_hash($password, \PASSWORD_DEFAULT); } $this->db->prepare("INSERT INTO arsse_users(id,password) values(?,?)", "str", "str")->runArray([$user,$hash]); @@ -123,10 +124,10 @@ class Database { } public function userRemove(string $user): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } - if($this->db->prepare("DELETE from arsse_users where id is ?", "str")->run($user)->changes() < 1) { + if ($this->db->prepare("DELETE from arsse_users where id is ?", "str")->run($user)->changes() < 1) { throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); } return true; @@ -134,20 +135,20 @@ class Database { public function userList(string $domain = null): array { $out = []; - if($domain !== null) { - if(!Arsse::$user->authorize("@".$domain, __FUNCTION__)) { + if ($domain !== null) { + if (!Arsse::$user->authorize("@".$domain, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $domain]); } - $domain = str_replace(["\\","%","_"],["\\\\", "\\%", "\\_"], $domain); + $domain = str_replace(["\\","%","_"], ["\\\\", "\\%", "\\_"], $domain); $domain = "%@".$domain; - foreach($this->db->prepare("SELECT id from arsse_users where id like ?", "str")->run($domain) as $user) { + foreach ($this->db->prepare("SELECT id from arsse_users where id like ?", "str")->run($domain) as $user) { $out[] = $user['id']; } } else { - if(!Arsse::$user->authorize("", __FUNCTION__)) { + if (!Arsse::$user->authorize("", __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => "global"]); } - foreach($this->db->query("SELECT id from arsse_users") as $user) { + foreach ($this->db->query("SELECT id from arsse_users") as $user) { $out[] = $user['id']; } } @@ -155,25 +156,25 @@ class Database { } public function userPasswordGet(string $user): string { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - } else if(!$this->userExists($user)) { + } elseif (!$this->userExists($user)) { throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); } return (string) $this->db->prepare("SELECT password from arsse_users where id is ?", "str")->run($user)->getValue(); } public function userPasswordSet(string $user, string $password = null): string { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - } else if(!$this->userExists($user)) { + } elseif (!$this->userExists($user)) { throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); } - if($password===null) { + if ($password===null) { $password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); } $hash = ""; - if(strlen($password) > 0) { + if (strlen($password) > 0) { $hash = password_hash($password, \PASSWORD_DEFAULT); } $this->db->prepare("UPDATE arsse_users set password = ? where id is ?", "str", "str")->run($hash, $user); @@ -181,20 +182,20 @@ class Database { } public function userPropertiesGet(string $user): array { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } $prop = $this->db->prepare("SELECT name,rights from arsse_users where id is ?", "str")->run($user)->getRow(); - if(!$prop) { + if (!$prop) { throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); } return $prop; } public function userPropertiesSet(string $user, array $properties): array { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - } else if(!$this->userExists($user)) { + } elseif (!$this->userExists($user)) { throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); } $valid = [ // FIXME: add future properties @@ -206,16 +207,16 @@ class Database { } public function userRightsGet(string $user): int { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } return (int) $this->db->prepare("SELECT rights from arsse_users where id is ?", "str")->run($user)->getValue(); } public function userRightsSet(string $user, int $rights): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__, $rights)) { + if (!Arsse::$user->authorize($user, __FUNCTION__, $rights)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - } else if(!$this->userExists($user)) { + } elseif (!$this->userExists($user)) { throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); } $this->db->prepare("UPDATE arsse_users set rights = ? where id is ?", "int", "str")->run($rights, $user); @@ -224,30 +225,30 @@ class Database { public function folderAdd(string $user, array $data): int { // If the user isn't authorized to perform this action then throw an exception. - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } // if the desired folder name is missing or invalid, throw an exception - if(!array_key_exists("name", $data) || $data['name']=="") { + if (!array_key_exists("name", $data) || $data['name']=="") { throw new Db\ExceptionInput("missing", ["action" => __FUNCTION__, "field" => "name"]); - } else if(!strlen(trim($data['name']))) { + } elseif (!strlen(trim($data['name']))) { throw new Db\ExceptionInput("whitespace", ["action" => __FUNCTION__, "field" => "name"]); } // normalize folder's parent, if there is one $parent = array_key_exists("parent", $data) ? (int) $data['parent'] : 0; - if($parent===0) { + if ($parent===0) { // if no parent is specified, do nothing $parent = null; } else { // if a parent is specified, make sure it exists and belongs to the user; get its root (first-level) folder if it's a nested folder $p = $this->db->prepare("SELECT id from arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $parent)->getValue(); - if(!$p) { + if (!$p) { throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "parent", 'id' => $parent]); } } // check if a folder by the same name already exists, because nulls are wonky in SQL // FIXME: How should folder name be compared? Should a Unicode normalization be applied before comparison and insertion? - if($this->db->prepare("SELECT count(*) from arsse_folders where owner is ? and parent is ? and name is ?", "str", "int", "str")->run($user, $parent, $data['name'])->getValue() > 0) { + if ($this->db->prepare("SELECT count(*) from arsse_folders where owner is ? and parent is ? and name is ?", "str", "int", "str")->run($user, $parent, $data['name'])->getValue() > 0) { throw new Db\ExceptionInput("constraintViolation"); // FIXME: There needs to be a practical message here } // actually perform the insert (!) @@ -256,17 +257,17 @@ class Database { public function folderList(string $user, int $parent = null, bool $recursive = true): Db\Result { // if the user isn't authorized to perform this action then throw an exception. - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } // check to make sure the parent exists, if one is specified - if(!is_null($parent)) { - if(!$this->db->prepare("SELECT count(*) from arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $parent)->getValue()) { + if (!is_null($parent)) { + if (!$this->db->prepare("SELECT count(*) from arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $parent)->getValue()) { throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "parent", 'id' => $parent]); } } // if we're not returning a recursive list we can use a simpler query - if(!$recursive) { + if (!$recursive) { return $this->db->prepare("SELECT id,name,parent from arsse_folders where owner is ? and parent is ?", "str", "int")->run($user, $parent); } else { return $this->db->prepare( @@ -277,45 +278,45 @@ class Database { } public function folderRemove(string $user, int $id): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } $changes = $this->db->prepare("DELETE FROM arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $id)->changes(); - if(!$changes) { + if (!$changes) { throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]); } return true; } public function folderPropertiesGet(string $user, int $id): array { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } $props = $this->db->prepare("SELECT id,name,parent from arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $id)->getRow(); - if(!$props) { + if (!$props) { throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]); } return $props; } public function folderPropertiesSet(string $user, int $id, array $data): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } // validate the folder ID and, if specified, the parent to move it to $parent = null; - if(array_key_exists("parent", $data)) { + if (array_key_exists("parent", $data)) { $parent = $data['parent']; } $f = $this->folderValidateId($user, $id, $parent, true); // if a new name is specified, validate it - if(array_key_exists("name", $data)) { + if (array_key_exists("name", $data)) { $this->folderValidateName($data['name']); } $data = array_merge($f, $data); // check to make sure the target folder name/location would not create a duplicate (we must do this check because null is not distinct in SQL) $existing = $this->db->prepare("SELECT id from arsse_folders where owner is ? and parent is ? and name is ?", "str", "int", "str")->run($user, $data['parent'], $data['name'])->getValue(); - if(!is_null($existing) && $existing != $id) { + if (!is_null($existing) && $existing != $id) { throw new Db\ExceptionInput("constraintViolation"); // FIXME: There needs to be a practical message here } $valid = [ @@ -327,32 +328,32 @@ class Database { } protected function folderValidateId(string $user, int $id = null, int $parent = null, bool $subject = false): array { - if(is_null($id)) { + if (is_null($id)) { // if no ID is specified this is a no-op, unless a parent is specified, which is always a circular dependence (the root cannot be moved) - if(!is_null($parent)) { + if (!is_null($parent)) { throw new Db\ExceptionInput("circularDependence", ["action" => $this->caller(), "field" => "parent", 'id' => $parent]); // @codeCoverageIgnore } return ['name' => null, 'parent' => null]; } // check whether the folder exists and is owned by the user $f = $this->db->prepare("SELECT name,parent from arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $id)->getRow(); - if(!$f) { + if (!$f) { throw new Db\ExceptionInput($subject ? "subjectMissing" : "idMissing", ["action" => $this->caller(), "field" => "folder", 'id' => $parent]); } // if we're moving a folder to a new parent, check that the parent is valid - if(!is_null($parent)) { + if (!is_null($parent)) { // make sure both that the parent exists, and that the parent is not either the folder itself or one of its children (a circular dependence) $p = $this->db->prepare( "WITH RECURSIVE folders(id) as (SELECT id from arsse_folders where owner is ? and id is ? union select arsse_folders.id from arsse_folders join folders on arsse_folders.parent=folders.id) ". "SELECT id,(id not in (select id from folders)) as valid from arsse_folders where owner is ? and id is ?", "str", "int", "str", "int" )->run($user, $id, $user, $parent)->getRow(); - if(!$p) { + if (!$p) { // if the parent doesn't exist or doesn't below to the user, throw an exception throw new Db\ExceptionInput("idMissing", ["action" => $this->caller(), "field" => "parent", 'id' => $parent]); } else { // if using the desired parent would create a circular dependence, throw a different exception - if(!$p['valid']) { + if (!$p['valid']) { throw new Db\ExceptionInput("circularDependence", ["action" => $this->caller(), "field" => "parent", 'id' => $parent]); } } @@ -362,9 +363,9 @@ class Database { protected function folderValidateName($name): bool { $name = (string) $name; - if(!strlen($name)) { + if (!strlen($name)) { throw new Db\ExceptionInput("missing", ["action" => $this->caller(), "field" => "name"]); - } else if(!strlen(trim($name))) { + } elseif (!strlen(trim($name))) { throw new Db\ExceptionInput("whitespace", ["action" => $this->caller(), "field" => "name"]); } else { return true; @@ -372,18 +373,18 @@ class Database { } public function subscriptionAdd(string $user, string $url, string $fetchUser = "", string $fetchPassword = ""): int { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } // check to see if the feed exists $feedID = $this->db->prepare("SELECT id from arsse_feeds where url is ? and username is ? and password is ?", "str", "str", "str")->run($url, $fetchUser, $fetchPassword)->getValue(); - if(is_null($feedID)) { + if (is_null($feedID)) { // if the feed doesn't exist add it to the database; we do this unconditionally so as to lock SQLite databases for as little time as possible $feedID = $this->db->prepare('INSERT INTO arsse_feeds(url,username,password) values(?,?,?)', 'str', 'str', 'str')->run($url, $fetchUser, $fetchPassword)->lastId(); try { // perform an initial update on the newly added feed $this->feedUpdate($feedID, true); - } catch(\Throwable $e) { + } catch (\Throwable $e) { // if the update fails, delete the feed we just added $this->db->prepare('DELETE from arsse_feeds where id is ?', 'int')->run($feedID); throw $e; @@ -394,7 +395,7 @@ class Database { } public function subscriptionList(string $user, int $folder = null, int $id = null): Db\Result { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } // create a complex query @@ -415,11 +416,11 @@ class Database { $q->setCTE("user(user)", "SELECT ?", "str", $user); // the subject user; this way we only have to pass it to prepare() once // topmost folders belonging to the user $q->setCTE("topmost(f_id,top)", "SELECT id,id from arsse_folders join user on owner is user where parent is null union select id,top from arsse_folders join topmost on parent=f_id"); - if(!is_null($id)) { + if (!is_null($id)) { // this condition facilitates the implementation of subscriptionPropertiesGet, which would otherwise have to duplicate the complex query; it takes precedence over a specified folder // if an ID is specified, add a suitable WHERE condition and bindings $q->setWhere("arsse_subscriptions.id is ?", "int", $id); - } else if(!is_null($folder)) { + } elseif (!is_null($folder)) { // if a folder is specified, make sure it exists $this->folderValidateId($user, $folder); // if it does exist, add a common table expression to list it and its children so that we select from the entire subtree @@ -431,50 +432,50 @@ class Database { } public function subscriptionRemove(string $user, int $id): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } $changes = $this->db->prepare("DELETE from arsse_subscriptions where owner is ? and id is ?", "str", "int")->run($user, $id)->changes(); - if(!$changes) { + if (!$changes) { throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]); } return true; } public function subscriptionPropertiesGet(string $user, int $id): array { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } // disable authorization checks for the list call Arsse::$user->authorizationEnabled(false); $sub = $this->subscriptionList($user, null, $id)->getRow(); Arsse::$user->authorizationEnabled(true); - if(!$sub) { + if (!$sub) { throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id]); } return $sub; } public function subscriptionPropertiesSet(string $user, int $id, array $data): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } $tr = $this->db->begin(); - if(!$this->db->prepare("SELECT count(*) from arsse_subscriptions where owner is ? and id is ?", "str", "int")->run($user, $id)->getValue()) { + if (!$this->db->prepare("SELECT count(*) from arsse_subscriptions where owner is ? and id is ?", "str", "int")->run($user, $id)->getValue()) { // if the ID doesn't exist or doesn't belong to the user, throw an exception throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id]); } - if(array_key_exists("folder", $data)) { + if (array_key_exists("folder", $data)) { // ensure the target folder exists and belong to the user $this->folderValidateId($user, $data['folder']); } - if(array_key_exists("title", $data)) { + if (array_key_exists("title", $data)) { // if the title is null, this signals intended use of the default title; otherwise make sure it's not effectively an empty string - if(!is_null($data['title'])) { + if (!is_null($data['title'])) { $title = (string) $data['title']; - if(!strlen($title)) { + if (!strlen($title)) { throw new Db\ExceptionInput("missing", ["action" => __FUNCTION__, "field" => "title"]); - } else if(!strlen(trim($title))) { + } elseif (!strlen(trim($title))) { throw new Db\ExceptionInput("whitespace", ["action" => __FUNCTION__, "field" => "title"]); } $data['title'] = $title; @@ -494,7 +495,7 @@ class Database { protected function subscriptionValidateId(string $user, int $id): array { $out = $this->db->prepare("SELECT feed from arsse_subscriptions where id is ? and owner is ?", "int", "str")->run($id, $user)->getRow(); - if(!$out) { + if (!$out) { throw new Db\ExceptionInput("idMissing", ["action" => $this->caller(), "field" => "subscription", 'id' => $id]); } return $out; @@ -502,14 +503,14 @@ class Database { public function feedListStale(): array { $feeds = $this->db->query("SELECT id from arsse_feeds where next_fetch <= CURRENT_TIMESTAMP")->getAll(); - return array_column($feeds,'id'); + return array_column($feeds, 'id'); } public function feedUpdate(int $feedID, bool $throwError = false): bool { $tr = $this->db->begin(); // check to make sure the feed exists $f = $this->db->prepare("SELECT url, username, password, modified, etag, err_count, scrape FROM arsse_feeds where id is ?", "int")->run($feedID)->getRow(); - if(!$f) { + if (!$f) { throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $feedID]); } // determine whether the feed's items should be scraped for full content from the source Web site @@ -519,7 +520,7 @@ class Database { // error instead of failing; if other exceptions are thrown, we should simply roll back try { $feed = new Feed($feedID, $f['url'], (string) Date::transform($f['modified'], "http", "sql"), $f['etag'], $f['username'], $f['password'], $scrape); - if(!$feed->modified) { + if (!$feed->modified) { // if the feed hasn't changed, just compute the next fetch time and record it $this->db->prepare("UPDATE arsse_feeds SET updated = CURRENT_TIMESTAMP, next_fetch = ? WHERE id is ?", 'datetime', 'int')->run($feed->nextFetch, $feedID); $tr->commit(); @@ -528,38 +529,38 @@ class Database { } catch (Feed\Exception $e) { // update the database with the resultant error and the next fetch time, incrementing the error count $this->db->prepare( - "UPDATE arsse_feeds SET updated = CURRENT_TIMESTAMP, next_fetch = ?, err_count = err_count + 1, err_msg = ? WHERE id is ?", + "UPDATE arsse_feeds SET updated = CURRENT_TIMESTAMP, next_fetch = ?, err_count = err_count + 1, err_msg = ? WHERE id is ?", 'datetime', 'str', 'int' - )->run(Feed::nextFetchOnError($f['err_count']), $e->getMessage(),$feedID); + )->run(Feed::nextFetchOnError($f['err_count']), $e->getMessage(), $feedID); $tr->commit(); - if($throwError) { + if ($throwError) { throw $e; } return false; } //prepare the necessary statements to perform the update - if(sizeof($feed->newItems) || sizeof($feed->changedItems)) { + if (sizeof($feed->newItems) || sizeof($feed->changedItems)) { $qInsertEnclosure = $this->db->prepare("INSERT INTO arsse_enclosures(article,url,type) values(?,?,?)", 'int', 'str', 'str'); $qInsertCategory = $this->db->prepare("INSERT INTO arsse_categories(article,name) values(?,?)", 'int', 'str'); $qInsertEdition = $this->db->prepare("INSERT INTO arsse_editions(article) values(?)", 'int'); } - if(sizeof($feed->newItems)) { + if (sizeof($feed->newItems)) { $qInsertArticle = $this->db->prepare( "INSERT INTO arsse_articles(url,title,author,published,edited,guid,content,url_title_hash,url_content_hash,title_content_hash,feed) values(?,?,?,?,?,?,?,?,?,?,?)", 'str', 'str', 'str', 'datetime', 'datetime', 'str', 'str', 'str', 'str', 'str', 'int' ); } - if(sizeof($feed->changedItems)) { + if (sizeof($feed->changedItems)) { $qDeleteEnclosures = $this->db->prepare("DELETE FROM arsse_enclosures WHERE article is ?", 'int'); $qDeleteCategories = $this->db->prepare("DELETE FROM arsse_categories WHERE article is ?", 'int'); $qClearReadMarks = $this->db->prepare("UPDATE arsse_marks SET read = 0, modified = CURRENT_TIMESTAMP WHERE article is ? and read is 1", 'int'); $qUpdateArticle = $this->db->prepare( - "UPDATE arsse_articles SET url = ?, title = ?, author = ?, published = ?, edited = ?, modified = CURRENT_TIMESTAMP, guid = ?, content = ?, url_title_hash = ?, url_content_hash = ?, title_content_hash = ? WHERE id is ?", + "UPDATE arsse_articles SET url = ?, title = ?, author = ?, published = ?, edited = ?, modified = CURRENT_TIMESTAMP, guid = ?, content = ?, url_title_hash = ?, url_content_hash = ?, title_content_hash = ? WHERE id is ?", 'str', 'str', 'str', 'datetime', 'datetime', 'str', 'str', 'str', 'str', 'str', 'int' ); } // actually perform updates - foreach($feed->newItems as $article) { + foreach ($feed->newItems as $article) { $articleID = $qInsertArticle->run( $article->url, $article->title, @@ -573,15 +574,15 @@ class Database { $article->titleContentHash, $feedID )->lastId(); - if($article->enclosureUrl) { - $qInsertEnclosure->run($articleID,$article->enclosureUrl,$article->enclosureType); + if ($article->enclosureUrl) { + $qInsertEnclosure->run($articleID, $article->enclosureUrl, $article->enclosureType); } - foreach($article->categories as $c) { + foreach ($article->categories as $c) { $qInsertCategory->run($articleID, $c); } $qInsertEdition->run($articleID); } - foreach($feed->changedItems as $articleID => $article) { + foreach ($feed->changedItems as $articleID => $article) { $qUpdateArticle->run( $article->url, $article->title, @@ -597,10 +598,10 @@ class Database { ); $qDeleteEnclosures->run($articleID); $qDeleteCategories->run($articleID); - if($article->enclosureUrl) { - $qInsertEnclosure->run($articleID,$article->enclosureUrl,$article->enclosureType); + if ($article->enclosureUrl) { + $qInsertEnclosure->run($articleID, $article->enclosureUrl, $article->enclosureType); } - foreach($article->categories as $c) { + foreach ($article->categories as $c) { $qInsertCategory->run($articleID, $c); } $qInsertEdition->run($articleID); @@ -608,7 +609,7 @@ class Database { } // lastly update the feed database itself with updated information. $this->db->prepare( - "UPDATE arsse_feeds SET url = ?, title = ?, favicon = ?, source = ?, updated = CURRENT_TIMESTAMP, modified = ?, etag = ?, err_count = 0, err_msg = '', next_fetch = ?, size = ? WHERE id is ?", + "UPDATE arsse_feeds SET url = ?, title = ?, favicon = ?, source = ?, updated = CURRENT_TIMESTAMP, modified = ?, etag = ?, err_count = 0, err_msg = '', next_fetch = ?, size = ? WHERE id is ?", 'str', 'str', 'str', 'str', 'datetime', 'str', 'datetime', 'int', 'int' )->run( $feed->data->feedUrl, @@ -633,7 +634,7 @@ class Database { $this->db->query("UPDATE arsse_feeds set orphaned = CURRENT_TIMESTAMP where orphaned is null and not exists(SELECT id from arsse_subscriptions where feed is arsse_feeds.id)"); // finally delete feeds that have been orphaned longer than the retention period $limit = Date::normalize("now"); - if(Arsse::$conf->purgeFeeds) { + if (Arsse::$conf->purgeFeeds) { // if there is a retention period specified, compute it; otherwise feed are deleted immediatelty $limit->sub(new \DateInterval(Arsse::$conf->purgeFeeds)); } @@ -645,29 +646,29 @@ class Database { public function feedMatchLatest(int $feedID, int $count): Db\Result { return $this->db->prepare( - "SELECT id, edited, guid, url_title_hash, url_content_hash, title_content_hash FROM arsse_articles WHERE feed is ? ORDER BY modified desc, id desc limit ?", + "SELECT id, edited, guid, url_title_hash, url_content_hash, title_content_hash FROM arsse_articles WHERE feed is ? ORDER BY modified desc, id desc limit ?", 'int', 'int' )->run($feedID, $count); } public function feedMatchIds(int $feedID, array $ids = [], array $hashesUT = [], array $hashesUC = [], array $hashesTC = []): Db\Result { // compile SQL IN() clauses and necessary type bindings for the four identifier lists - list($cId, $tId) = $this->generateIn($ids, "str"); + list($cId, $tId) = $this->generateIn($ids, "str"); list($cHashUT, $tHashUT) = $this->generateIn($hashesUT, "str"); list($cHashUC, $tHashUC) = $this->generateIn($hashesUC, "str"); list($cHashTC, $tHashTC) = $this->generateIn($hashesTC, "str"); // perform the query return $articles = $this->db->prepare( - "SELECT id, edited, guid, url_title_hash, url_content_hash, title_content_hash FROM arsse_articles WHERE feed is ? and (guid in($cId) or url_title_hash in($cHashUT) or url_content_hash in($cHashUC) or title_content_hash in($cHashTC))", + "SELECT id, edited, guid, url_title_hash, url_content_hash, title_content_hash FROM arsse_articles WHERE feed is ? and (guid in($cId) or url_title_hash in($cHashUT) or url_content_hash in($cHashUC) or title_content_hash in($cHashTC))", 'int', $tId, $tHashUT, $tHashUC, $tHashTC )->run($feedID, $ids, $hashesUT, $hashesUC, $hashesTC); } public function articleList(string $user, Context $context = null): Db\Result { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } - if(!$context) { + if (!$context) { $context = new Context; } $q = new Query( @@ -696,12 +697,12 @@ class Database { $q->setOrder("edition".($context->reverse ? " desc" : "")); $q->setLimit($context->limit, $context->offset); $q->setCTE("user(user)", "SELECT ?", "str", $user); - if($context->subscription()) { + if ($context->subscription()) { // if a subscription is specified, make sure it exists $id = $this->subscriptionValidateId($user, $context->subscription)['feed']; // add a basic CTE that will join in only the requested subscription $q->setCTE("subscribed_feeds(id,sub)", "SELECT ?,?", ["int","int"], [$id,$context->subscription]); - } else if($context->folder()) { + } elseif ($context->folder()) { // if a folder is specified, make sure it exists $this->folderValidateId($user, $context->folder); // if it does exist, add a common table expression to list it and its children so that we select from the entire subtree @@ -713,24 +714,24 @@ class Database { $q->setCTE("subscribed_feeds(id,sub)", "SELECT feed,id from arsse_subscriptions join user on user is owner"); } // filter based on edition offset - if($context->oldestEdition()) { + if ($context->oldestEdition()) { $q->setWhere("edition >= ?", "int", $context->oldestEdition); } - if($context->latestEdition()) { + if ($context->latestEdition()) { $q->setWhere("edition <= ?", "int", $context->latestEdition); } // filter based on lastmod time - if($context->modifiedSince()) { + if ($context->modifiedSince()) { $q->setWhere("modified_date >= ?", "datetime", $context->modifiedSince); } - if($context->notModifiedSince()) { + if ($context->notModifiedSince()) { $q->setWhere("modified_date <= ?", "datetime", $context->notModifiedSince); } // filter for un/read and un/starred status if specified - if($context->unread()) { + if ($context->unread()) { $q->setWhere("unread is ?", "bool", $context->unread); } - if($context->starred()) { + if ($context->starred()) { $q->setWhere("starred is ?", "bool", $context->starred); } // perform the query and return results @@ -738,10 +739,10 @@ class Database { } public function articleMark(string $user, array $data, Context $context = null): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } - if(!$context) { + if (!$context) { $context = new Context; } // sanitize input @@ -771,19 +772,19 @@ class Database { // wrap this UPDATE and INSERT together into a transaction $tr = $this->begin(); // if an edition context is specified, make sure it's valid - if($context->edition()) { + if ($context->edition()) { // make sure the edition exists $edition = $this->articleValidateEdition($user, $context->edition); // if the edition is not the latest, do not mark the read flag - if(!$edition['current']) { + if (!$edition['current']) { $values[0] = null; } - } else if($context->article()) { + } elseif ($context->article()) { // otherwise if an article context is specified, make sure it's valid $this->articleValidateId($user, $context->article); } // execute each query in sequence - foreach($queries as $query) { + foreach ($queries as $query) { // first build the query which will select the target articles; we will later turn this into a CTE for the actual query that manipulates the articles $q = new Query( "SELECT @@ -802,12 +803,12 @@ class Database { $q->setCTE("user(user)", "SELECT ?", "str", $user); // common table expression with the values to set $q->setCTE("target_values(read,starred)", "SELECT ?,?", ["bool","bool"], $values); - if($context->subscription()) { + if ($context->subscription()) { // if a subscription is specified, make sure it exists $id = $this->subscriptionValidateId($user, $context->subscription)['feed']; // add a basic CTE that will join in only the requested subscription $q->setCTE("subscribed_feeds(id,sub)", "SELECT ?,?", ["int","int"], [$id,$context->subscription], "join subscribed_feeds on feed is subscribed_feeds.id"); - } else if($context->folder()) { + } elseif ($context->folder()) { // if a folder is specified, make sure it exists $this->folderValidateId($user, $context->folder); // if it does exist, add a common table expression to list it and its children so that we select from the entire subtree @@ -818,18 +819,18 @@ class Database { // otherwise add a CTE for all the user's subscriptions $q->setCTE("subscribed_feeds(id,sub)", "SELECT feed,id from arsse_subscriptions join user on user is owner", [], [], "join subscribed_feeds on feed is subscribed_feeds.id"); } - if($context->edition()) { + if ($context->edition()) { // if an edition is specified, filter for its previously identified article $q->setWhere("arsse_articles.id is ?", "int", $edition['article']); - } else if($context->article()) { + } elseif ($context->article()) { // if an article is specified, filter for it (it has already been validated above) $q->setWhere("arsse_articles.id is ?", "int", $context->article); } - if($context->editions()) { + if ($context->editions()) { // if multiple specific editions have been requested, prepare a CTE to list them and their articles - if(!$context->editions) { + if (!$context->editions) { throw new Db\ExceptionInput("tooShort", ['field' => "editions", 'action' => __FUNCTION__, 'min' => 1]); // must have at least one array element - } else if(sizeof($context->editions) > 50) { + } elseif (sizeof($context->editions) > 50) { throw new Db\ExceptionInput("tooLong", ['field' => "editions", 'action' => __FUNCTION__, 'max' => 50]); // must not have more than 50 array elements } list($inParams, $inTypes) = $this->generateIn($context->editions, "int"); @@ -839,15 +840,15 @@ class Database { $context->editions ); $q->setWhere("arsse_articles.id in (select id from requested_articles)"); - } else if($context->articles()) { + } elseif ($context->articles()) { // if multiple specific articles have been requested, prepare a CTE to list them and their articles - if(!$context->articles) { + if (!$context->articles) { throw new Db\ExceptionInput("tooShort", ['field' => "articles", 'action' => __FUNCTION__, 'min' => 1]); // must have at least one array element - } else if(sizeof($context->articles) > 50) { + } elseif (sizeof($context->articles) > 50) { throw new Db\ExceptionInput("tooLong", ['field' => "articles", 'action' => __FUNCTION__, 'max' => 50]); // must not have more than 50 array elements } list($inParams, $inTypes) = $this->generateIn($context->articles, "int"); - $q->setCTE("requested_articles(id,edition)", + $q->setCTE("requested_articles(id,edition)", "SELECT id,(select max(id) from arsse_editions where article is arsse_articles.id) as edition from arsse_articles where arsse_articles.id in ($inParams)", $inTypes, $context->articles @@ -858,17 +859,17 @@ class Database { $q->setCTE("requested_articles(id,edition)", "SELECT 'empty','table' where 1 is 0"); } // filter based on edition offset - if($context->oldestEdition()) { + if ($context->oldestEdition()) { $q->setWhere("edition >= ?", "int", $context->oldestEdition); } - if($context->latestEdition()) { + if ($context->latestEdition()) { $q->setWhere("edition <= ?", "int", $context->latestEdition); } // filter based on lastmod time - if($context->modifiedSince()) { + if ($context->modifiedSince()) { $q->setWhere("modified_date >= ?", "datetime", $context->modifiedSince); } - if($context->notModifiedSince()) { + if ($context->notModifiedSince()) { $q->setWhere("modified_date <= ?", "datetime", $context->notModifiedSince); } // push the current query onto the CTE stack and execute the query we're actually interested in @@ -882,7 +883,7 @@ class Database { } public function articleStarredCount(string $user): int { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } return $this->db->prepare("SELECT count(*) from arsse_marks where starred is 1 and subscription in (select id from arsse_subscriptions where owner is ?)", "str")->run($user)->getValue(); @@ -913,14 +914,14 @@ class Database { ); $limitRead = null; $limitUnread = null; - if(Arsse::$conf->purgeArticlesRead) { + if (Arsse::$conf->purgeArticlesRead) { $limitRead = Date::sub(Arsse::$conf->purgeArticlesRead); } - if(Arsse::$conf->purgeArticlesUnread) { + if (Arsse::$conf->purgeArticlesUnread) { $limitUnread = Date::sub(Arsse::$conf->purgeArticlesUnread); } $feeds = $this->db->query("SELECT id, size from arsse_feeds")->getAll(); - foreach($feeds as $feed) { + foreach ($feeds as $feed) { $query->run($feed['id'], $feed['size'], $limitUnread, $limitRead); } return true; @@ -938,7 +939,7 @@ class Database { arsse_articles.id is ? and arsse_subscriptions.owner is ?", "int", "str" )->run($id, $user)->getRow(); - if(!$out) { + if (!$out) { throw new Db\ExceptionInput("subjectMissing", ["action" => $this->caller(), "field" => "article", 'id' => $id]); } return $out; @@ -958,21 +959,21 @@ class Database { edition is ? and arsse_subscriptions.owner is ?", "int", "str" )->run($id, $user)->getRow(); - if(!$out) { + if (!$out) { throw new Db\ExceptionInput("subjectMissing", ["action" => $this->caller(), "field" => "edition", 'id' => $id]); } return $out; } public function editionLatest(string $user, Context $context = null): int { - if(!Arsse::$user->authorize($user, __FUNCTION__)) { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } - if(!$context) { + if (!$context) { $context = new Context; } $q = new Query("SELECT max(arsse_editions.id) from arsse_editions left join arsse_articles on article is arsse_articles.id left join arsse_feeds on arsse_articles.feed is arsse_feeds.id"); - if($context->subscription()) { + if ($context->subscription()) { // if a subscription is specified, make sure it exists $id = $this->subscriptionValidateId($user, $context->subscription)['feed']; // a simple WHERE clause is required here @@ -983,4 +984,4 @@ class Database { } return (int) $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->getValue(); } -} \ No newline at end of file +} diff --git a/lib/Db/AbstractDriver.php b/lib/Db/AbstractDriver.php index e8d1cc1..7092aa3 100644 --- a/lib/Db/AbstractDriver.php +++ b/lib/Db/AbstractDriver.php @@ -7,16 +7,16 @@ abstract class AbstractDriver implements Driver { protected $transDepth = 0; protected $transStatus = []; - public abstract function prepareArray(string $query, array $paramTypes): Statement; - protected abstract function lock(): bool; - protected abstract function unlock(bool $rollback = false) : bool; + abstract public function prepareArray(string $query, array $paramTypes): Statement; + abstract protected function lock(): bool; + abstract protected function unlock(bool $rollback = false) : bool; /** @codeCoverageIgnore */ public function schemaVersion(): int { // FIXME: generic schemaVersion() will need to be covered for database engines other than SQLite try { return (int) $this->query("SELECT value from arsse_meta where key is schema_version")->getValue(); - } catch(Exception $e) { + } catch (Exception $e) { return 0; } } @@ -26,7 +26,7 @@ abstract class AbstractDriver implements Driver { } public function savepointCreate(bool $lock = false): int { - if($lock && !$this->transDepth) { + if ($lock && !$this->transDepth) { $this->lock(); $this->locked = true; } @@ -36,17 +36,17 @@ abstract class AbstractDriver implements Driver { } public function savepointRelease(int $index = null): bool { - if(is_null($index)) { + if (is_null($index)) { $index = $this->transDepth; } - if(array_key_exists($index, $this->transStatus)) { - switch($this->transStatus[$index]) { + if (array_key_exists($index, $this->transStatus)) { + switch ($this->transStatus[$index]) { case self::TR_PEND: $this->exec("RELEASE SAVEPOINT arsse_".$index); $this->transStatus[$index] = self::TR_COMMIT; $a = $index; - while(++$a && $a <= $this->transDepth) { - if($this->transStatus[$a] <= self::TR_PEND) { + while (++$a && $a <= $this->transDepth) { + if ($this->transStatus[$a] <= self::TR_PEND) { $this->transStatus[$a] = self::TR_PEND_COMMIT; } } @@ -66,13 +66,13 @@ abstract class AbstractDriver implements Driver { default: throw new Exception("unknownSavepointStatus", $this->transStatus[$index]); //@codeCoverageIgnore } - if($index==$this->transDepth) { - while($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) { + if ($index==$this->transDepth) { + while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) { array_pop($this->transStatus); $this->transDepth--; } } - if(!$this->transDepth && $this->locked) { + if (!$this->transDepth && $this->locked) { $this->unlock(); $this->locked = false; } @@ -83,18 +83,18 @@ abstract class AbstractDriver implements Driver { } public function savepointUndo(int $index = null): bool { - if(is_null($index)) { + if (is_null($index)) { $index = $this->transDepth; } - if(array_key_exists($index, $this->transStatus)) { - switch($this->transStatus[$index]) { + if (array_key_exists($index, $this->transStatus)) { + switch ($this->transStatus[$index]) { case self::TR_PEND: $this->exec("ROLLBACK TRANSACTION TO SAVEPOINT arsse_".$index); $this->exec("RELEASE SAVEPOINT arsse_".$index); $this->transStatus[$index] = self::TR_ROLLBACK; $a = $index; - while(++$a && $a <= $this->transDepth) { - if($this->transStatus[$a] <= self::TR_PEND) { + while (++$a && $a <= $this->transDepth) { + if ($this->transStatus[$a] <= self::TR_PEND) { $this->transStatus[$a] = self::TR_PEND_ROLLBACK; } } @@ -114,13 +114,13 @@ abstract class AbstractDriver implements Driver { default: throw new Exception("unknownSavepointStatus", $this->transStatus[$index]); //@codeCoverageIgnore } - if($index==$this->transDepth) { - while($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) { + if ($index==$this->transDepth) { + while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) { array_pop($this->transStatus); $this->transDepth--; } } - if(!$this->transDepth && $this->locked) { + if (!$this->transDepth && $this->locked) { $this->unlock(true); $this->locked = false; } @@ -133,4 +133,4 @@ abstract class AbstractDriver implements Driver { public function prepare(string $query, ...$paramType): Statement { return $this->prepareArray($query, $paramType); } -} \ No newline at end of file +} diff --git a/lib/Db/AbstractStatement.php b/lib/Db/AbstractStatement.php index c21e04c..3ac5052 100644 --- a/lib/Db/AbstractStatement.php +++ b/lib/Db/AbstractStatement.php @@ -1,15 +1,15 @@ [], 'post' => []]; - abstract function runArray(array $values = []): Result; + abstract public function runArray(array $values = []): Result; public function run(...$values): Result { return $this->runArray($values); @@ -20,23 +20,23 @@ abstract class AbstractStatement implements Statement { } public function rebindArray(array $bindings, bool $append = false): bool { - if(!$append) { + if (!$append) { $this->types = []; } - foreach($bindings as $binding) { - if(is_array($binding)) { + foreach ($bindings as $binding) { + if (is_array($binding)) { // recursively flatten any arrays, which may be provided for SET or IN() clauses $this->rebindArray($binding, true); } else { $binding = trim(strtolower($binding)); - if(strpos($binding, "strict ")===0) { + if (strpos($binding, "strict ")===0) { // "strict" types' values may never be null; null values will later be cast to the type specified $this->isNullable[] = false; $binding = substr($binding, 7); } else { $this->isNullable[] = true; } - if(!array_key_exists($binding, self::TYPES)) { + if (!array_key_exists($binding, self::TYPES)) { throw new Exception("paramTypeInvalid", $binding); // @codeCoverageIgnore } $this->types[] = self::TYPES[$binding]; @@ -46,19 +46,19 @@ abstract class AbstractStatement implements Statement { } protected function cast($v, string $t, bool $nullable) { - switch($t) { + switch ($t) { case "date": - if(is_null($v) && !$nullable) { + if (is_null($v) && !$nullable) { $v = 0; } return Date::transform($v, "date"); case "time": - if(is_null($v) && !$nullable) { + if (is_null($v) && !$nullable) { $v = 0; } return Date::transform($v, "time"); case "datetime": - if(is_null($v) && !$nullable) { + if (is_null($v) && !$nullable) { $v = 0; } return Date::transform($v, "sql"); @@ -68,15 +68,15 @@ abstract class AbstractStatement implements Statement { case "binary": case "string": case "boolean": - if($t=="binary") { + if ($t=="binary") { $t = "string"; } - if($v instanceof \DateTimeInterface) { - if($t=="string") { + if ($v instanceof \DateTimeInterface) { + if ($t=="string") { return Date::transform($v, "sql"); } else { $v = $v->getTimestamp(); - settype($v, $t); + settype($v, $t); } } else { settype($v, $t); @@ -86,4 +86,4 @@ abstract class AbstractStatement implements Statement { throw new Exception("paramTypeUnknown", $type); // @codeCoverageIgnore } } -} \ No newline at end of file +} diff --git a/lib/Db/Driver.php b/lib/Db/Driver.php index 6ea63bc..4804795 100644 --- a/lib/Db/Driver.php +++ b/lib/Db/Driver.php @@ -9,26 +9,26 @@ interface Driver { const TR_PEND_COMMIT = -1; const TR_PEND_ROLLBACK = -2; - function __construct(); + public function __construct(); // returns a human-friendly name for the driver (for display in installer, for example) - static function driverName(): string; + public static function driverName(): string; // returns the version of the scheme of the opened database; if uninitialized should return 0 - function schemaVersion(): int; + public function schemaVersion(): int; // return a Transaction object - function begin(bool $lock = false): Transaction; + public function begin(bool $lock = false): Transaction; // manually begin a real or synthetic transactions, with real or synthetic nesting - function savepointCreate(): int; + public function savepointCreate(): int; // manually commit either the latest or all pending nested transactions - function savepointRelease(int $index = null): bool; + public function savepointRelease(int $index = null): bool; // manually rollback either the latest or all pending nested transactions - function savepointUndo(int $index = null): bool; + public function savepointUndo(int $index = null): bool; // attempt to perform an in-place upgrade of the database schema; this may be a no-op which always throws an exception - function schemaUpdate(int $to): bool; + public function schemaUpdate(int $to): bool; // execute one or more unsanitized SQL queries and return an indication of success - function exec(string $query): bool; + public function exec(string $query): bool; // perform a single unsanitized query and return a result set - function query(string $query): Result; + public function query(string $query): Result; // ready a prepared statement for later execution - function prepare(string $query, ...$paramType): Statement; - function prepareArray(string $query, array $paramTypes): Statement; -} \ No newline at end of file + public function prepare(string $query, ...$paramType): Statement; + public function prepareArray(string $query, array $paramTypes): Statement; +} diff --git a/lib/Db/Exception.php b/lib/Db/Exception.php index deec1e0..866de3a 100644 --- a/lib/Db/Exception.php +++ b/lib/Db/Exception.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Db; class Exception extends \JKingWeb\Arsse\AbstractException { -} \ No newline at end of file +} diff --git a/lib/Db/ExceptionInput.php b/lib/Db/ExceptionInput.php index 287c485..cc07d0f 100644 --- a/lib/Db/ExceptionInput.php +++ b/lib/Db/ExceptionInput.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Db; class ExceptionInput extends \JKingWeb\Arsse\AbstractException { -} \ No newline at end of file +} diff --git a/lib/Db/ExceptionSavepoint.php b/lib/Db/ExceptionSavepoint.php index 98a8271..a90839e 100644 --- a/lib/Db/ExceptionSavepoint.php +++ b/lib/Db/ExceptionSavepoint.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Db; class ExceptionSavepoint extends \JKingWeb\Arsse\AbstractException { -} \ No newline at end of file +} diff --git a/lib/Db/ExceptionTimeout.php b/lib/Db/ExceptionTimeout.php index 8de7512..d8f91fe 100644 --- a/lib/Db/ExceptionTimeout.php +++ b/lib/Db/ExceptionTimeout.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Db; class ExceptionTimeout extends \JKingWeb\Arsse\AbstractException { -} \ No newline at end of file +} diff --git a/lib/Db/Result.php b/lib/Db/Result.php index 012041b..1356a87 100644 --- a/lib/Db/Result.php +++ b/lib/Db/Result.php @@ -3,16 +3,16 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Db; interface Result extends \Iterator { - function current(); - function key(); - function next(); - function rewind(); - function valid(); + public function current(); + public function key(); + public function next(); + public function rewind(); + public function valid(); - function getRow(); - function getAll(): array; - function getValue(); + public function getRow(); + public function getAll(): array; + public function getValue(); - function changes(); - function lastId(); -} \ No newline at end of file + public function changes(); + public function lastId(); +} diff --git a/lib/Db/SQLite3/Driver.php b/lib/Db/SQLite3/Driver.php index a4f2642..02f9600 100644 --- a/lib/Db/SQLite3/Driver.php +++ b/lib/Db/SQLite3/Driver.php @@ -1,12 +1,12 @@ dbSQLite3File; - if(is_null($dbFile)) { + if (is_null($dbFile)) { // if no database file is specified in the configuration, use a suitable default $dbFile = \JKingWeb\Arsse\BASE."arsse.db"; } @@ -34,21 +34,21 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { $this->db->enableExceptions(true); $this->exec("PRAGMA journal_mode = wal"); $this->exec("PRAGMA foreign_keys = yes"); - } catch(\Throwable $e) { + } catch (\Throwable $e) { // if opening the database doesn't work, check various pre-conditions to find out what the problem might be $files = [ $dbFile, // main database file $dbFile."-wal", // write-ahead log journal $dbFile."-shm", // shared memory index ]; - foreach($files as $file) { - if(!file_exists($file) && !is_writable(dirname($file))) { + foreach ($files as $file) { + if (!file_exists($file) && !is_writable(dirname($file))) { throw new Exception("fileUncreatable", $file); - } else if(!is_readable($file) && !is_writable($file)) { + } elseif (!is_readable($file) && !is_writable($file)) { throw new Exception("fileUnusable", $file); - } else if(!is_readable($file)) { + } elseif (!is_readable($file)) { throw new Exception("fileUnreadable", $file); - } else if(!is_writable($file)) { + } elseif (!is_writable($file)) { throw new Exception("fileUnwritable", $file); } } @@ -64,12 +64,15 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { } public function __destruct() { - try{$this->db->close();} catch(\Exception $e) {} + try { + $this->db->close(); + } catch (\Exception $e) { + } unset($this->db); } - static public function driverName(): string { + public static function driverName(): string { return Arsse::$lang->msg("Driver.Db.SQLite3.Name"); } @@ -79,37 +82,37 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { public function schemaUpdate(int $to, string $basePath = null): bool { $ver = $this->schemaVersion(); - if(!Arsse::$conf->dbAutoUpdate) { + if (!Arsse::$conf->dbAutoUpdate) { throw new Exception("updateManual", ['version' => $ver, 'driver_name' => $this->driverName()]); - } else if($ver >= $to) { + } elseif ($ver >= $to) { throw new Exception("updateTooNew", ['difference' => ($ver - $to), 'current' => $ver, 'target' => $to, 'driver_name' => $this->driverName()]); } $sep = \DIRECTORY_SEPARATOR; $path = ($basePath ?? \JKingWeb\Arsse\BASE."sql").$sep."SQLite3".$sep; // lock the database $this->savepointCreate(true); - for($a = $this->schemaVersion(); $a < $to; $a++) { + for ($a = $this->schemaVersion(); $a < $to; $a++) { $this->savepointCreate(); try { $file = $path.$a.".sql"; - if(!file_exists($file)) { + if (!file_exists($file)) { throw new Exception("updateFileMissing", ['file' => $file, 'driver_name' => $this->driverName(), 'current' => $a]); - } else if(!is_readable($file)) { + } elseif (!is_readable($file)) { throw new Exception("updateFileUnreadable", ['file' => $file, 'driver_name' => $this->driverName(), 'current' => $a]); } $sql = @file_get_contents($file); - if($sql===false) { + if ($sql===false) { throw new Exception("updateFileUnusable", ['file' => $file, 'driver_name' => $this->driverName(), 'current' => $a]); // @codeCoverageIgnore } try { $this->exec($sql); - } catch(\Throwable $e) { + } catch (\Throwable $e) { throw new Exception("updateFileError", ['file' => $file, 'driver_name' => $this->driverName(), 'current' => $a, 'message' => $this->getError()]); } - if($this->schemaVersion() != $a+1) { + if ($this->schemaVersion() != $a+1) { throw new Exception("updateFileIncomplete", ['file' => $file, 'driver_name' => $this->driverName(), 'current' => $a]); } - } catch(\Throwable $e) { + } catch (\Throwable $e) { // undo any partial changes from the failed update $this->savepointUndo(); // commit any successful updates if updating by more than one version @@ -130,7 +133,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { public function exec(string $query): bool { try { return (bool) $this->db->exec($query); - } catch(\Exception $e) { + } catch (\Exception $e) { list($excClass, $excMsg, $excData) = $this->exceptionBuild(); throw new $excClass($excMsg, $excData); } @@ -139,7 +142,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { public function query(string $query): \JKingWeb\Arsse\Db\Result { try { $r = $this->db->query($query); - } catch(\Exception $e) { + } catch (\Exception $e) { list($excClass, $excMsg, $excData) = $this->exceptionBuild(); throw new $excClass($excMsg, $excData); } @@ -151,7 +154,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { public function prepareArray(string $query, array $paramTypes): \JKingWeb\Arsse\Db\Statement { try { $s = $this->db->prepare($query); - } catch(\Exception $e) { + } catch (\Exception $e) { list($excClass, $excMsg, $excData) = $this->exceptionBuild(); throw new $excClass($excMsg, $excData); } @@ -167,4 +170,4 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { $this->exec((!$rollback) ? "COMMIT" : "ROLLBACK"); return true; } -} \ No newline at end of file +} diff --git a/lib/Db/SQLite3/ExceptionBuilder.php b/lib/Db/SQLite3/ExceptionBuilder.php index b75e62e..e9f13a5 100644 --- a/lib/Db/SQLite3/ExceptionBuilder.php +++ b/lib/Db/SQLite3/ExceptionBuilder.php @@ -1,15 +1,14 @@ db->lastErrorCode()) { + switch ($this->db->lastErrorCode()) { case self::SQLITE_BUSY: return [ExceptionTimeout::class, 'general', $this->db->lastErrorMsg()]; case self::SQLITE_CONSTRAINT: @@ -20,4 +19,4 @@ trait ExceptionBuilder { return [Exception::class, 'engineErrorGeneral', $this->db->lastErrorMsg()]; } } -} \ No newline at end of file +} diff --git a/lib/Db/SQLite3/Result.php b/lib/Db/SQLite3/Result.php index 855c49a..477e460 100644 --- a/lib/Db/SQLite3/Result.php +++ b/lib/Db/SQLite3/Result.php @@ -14,7 +14,7 @@ class Result implements \JKingWeb\Arsse\Db\Result { public function getValue() { $this->next(); - if($this->valid()) { + if ($this->valid()) { $keys = array_keys($this->cur); return $this->cur[array_shift($keys)]; } @@ -28,7 +28,7 @@ class Result implements \JKingWeb\Arsse\Db\Result { public function getAll(): array { $out = []; - foreach($this as $row) { + foreach ($this as $row) { $out [] = $row; } return $out; @@ -52,7 +52,10 @@ class Result implements \JKingWeb\Arsse\Db\Result { } public function __destruct() { - try{$this->set->finalize();} catch(\Throwable $e) {} + try { + $this->set->finalize(); + } catch (\Throwable $e) { + } unset($this->set); } @@ -81,4 +84,4 @@ class Result implements \JKingWeb\Arsse\Db\Result { $this->cur = null; $this->set->reset(); } -} \ No newline at end of file +} diff --git a/lib/Db/SQLite3/Statement.php b/lib/Db/SQLite3/Statement.php index 38fafc3..6ca4787 100644 --- a/lib/Db/SQLite3/Statement.php +++ b/lib/Db/SQLite3/Statement.php @@ -1,6 +1,7 @@ st->close();} catch(\Throwable $e) {} + try { + $this->st->close(); + } catch (\Throwable $e) { + } unset($this->st); } @@ -42,7 +46,7 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement { $this->bindValues($values); try { $r = $this->st->execute(); - } catch(\Exception $e) { + } catch (\Exception $e) { list($excClass, $excMsg, $excData) = $this->exceptionBuild(); throw new $excClass($excMsg, $excData); } @@ -53,22 +57,22 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement { protected function bindValues(array $values, int $offset = 0): int { $a = $offset; - foreach($values as $value) { - if(is_array($value)) { + foreach ($values as $value) { + if (is_array($value)) { // recursively flatten any arrays, which may be provided for SET or IN() clauses $a += $this->bindValues($value, $a); - } else if(array_key_exists($a,$this->types)) { + } elseif (array_key_exists($a, $this->types)) { // if the parameter type is something other than the known values, this is an error assert(array_key_exists($this->types[$a], self::BINDINGS), new Exception("paramTypeUnknown", $this->types[$a])); // if the parameter type is null or the value is null (and the type is nullable), just bind null - if($this->types[$a]=="null" || ($this->isNullable[$a] && is_null($value))) { + if ($this->types[$a]=="null" || ($this->isNullable[$a] && is_null($value))) { $this->st->bindValue($a+1, null, \SQLITE3_NULL); - } else { + } else { // otherwise cast the value to the right type and bind the result $type = self::BINDINGS[$this->types[$a]]; $value = $this->cast($value, $this->types[$a], $this->isNullable[$a]); // re-adjust for null casts - if($value===null) { + if ($value===null) { $type = \SQLITE3_NULL; } // perform binding @@ -81,4 +85,4 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement { } return $a - $offset; } -} \ No newline at end of file +} diff --git a/lib/Db/Statement.php b/lib/Db/Statement.php index f128862..96bd288 100644 --- a/lib/Db/Statement.php +++ b/lib/Db/Statement.php @@ -27,8 +27,8 @@ interface Statement { "bit" => "boolean", ]; - function run(...$values): Result; - function runArray(array $values = []): Result; - function rebind(...$bindings): bool; - function rebindArray(array $bindings): bool; -} \ No newline at end of file + public function run(...$values): Result; + public function runArray(array $values = []): Result; + public function rebind(...$bindings): bool; + public function rebindArray(array $bindings): bool; +} diff --git a/lib/Db/Transaction.php b/lib/Db/Transaction.php index 964a358..69659f5 100644 --- a/lib/Db/Transaction.php +++ b/lib/Db/Transaction.php @@ -7,39 +7,39 @@ class Transaction { protected $pending = false; protected $drv; - function __construct(Driver $drv, bool $lock = false) { + public function __construct(Driver $drv, bool $lock = false) { $this->index = $drv->savepointCreate($lock); $this->drv = $drv; $this->pending = true; } - function __destruct() { - if($this->pending) { + public function __destruct() { + if ($this->pending) { try { $this->drv->savepointUndo($this->index); - } catch(\Throwable $e) { + } catch (\Throwable $e) { // do nothing } } } - function commit(): bool { + public function commit(): bool { $out = $this->drv->savepointRelease($this->index); $this->pending = false; return $out; } - function rollback(): bool { + public function rollback(): bool { $out = $this->drv->savepointUndo($this->index); $this->pending = false; return $out; } - function getIndex(): int { + public function getIndex(): int { return $this->index; } - function isPending(): bool { + public function isPending(): bool { return $this->pending; } -} \ No newline at end of file +} diff --git a/lib/Exception.php b/lib/Exception.php index 0d64bce..6fb65e7 100644 --- a/lib/Exception.php +++ b/lib/Exception.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse; class Exception extends AbstractException { -} \ No newline at end of file +} diff --git a/lib/ExceptionFatal.php b/lib/ExceptionFatal.php index 1d27bdf..263e5b3 100644 --- a/lib/ExceptionFatal.php +++ b/lib/ExceptionFatal.php @@ -6,4 +6,4 @@ class ExceptionFatal extends AbstractException { public function __construct($msg = "", $code = 0, $e = null) { \Exception::__construct($msg, $code, $e); } -} \ No newline at end of file +} diff --git a/lib/Feed.php b/lib/Feed.php index 57a62c9..a4dc476 100644 --- a/lib/Feed.php +++ b/lib/Feed.php @@ -1,6 +1,7 @@ download($url, $lastModified, $etag, $username, $password); // format the HTTP Last-Modified date returned $lastMod = $this->resource->getLastModified(); - if(strlen($lastMod)) { + if (strlen($lastMod)) { $this->lastModified = Date::normalize($lastMod, "http"); } $this->modified = $this->resource->isModified(); //parse the feed, if it has been modified - if($this->modified) { + if ($this->modified) { $this->parse(); // ascertain whether there are any articles not in the database $this->matchToDatabase($feedID); // if caching header fields are not sent by the server, try to ascertain a last-modified date from the feed contents - if(!$this->lastModified) { + if (!$this->lastModified) { $this->lastModified = $this->computeLastModified(); } // we only really care if articles have been modified; if there are no new articles, act as if the feed is unchanged - if(!sizeof($this->newItems) && !sizeof($this->changedItems)) { + if (!sizeof($this->newItems) && !sizeof($this->changedItems)) { $this->modified = false; } // if requested, scrape full content for any new and changed items - if($scrape) { + if ($scrape) { $this->scrape(); } } @@ -107,19 +108,19 @@ class Feed { // id doesn't exist. $content = $f->content.$f->enclosureUrl.$f->enclosureType; // if the item link URL and item title are both equal to the feed link URL, then the item has neither a link URL nor a title - if($f->url==$feed->siteUrl && $f->title==$feed->siteUrl) { + if ($f->url==$feed->siteUrl && $f->title==$feed->siteUrl) { $f->urlTitleHash = ""; } else { $f->urlTitleHash = hash('sha256', $f->url.$f->title); } // if the item link URL is equal to the feed link URL, it has no link URL; if there is additionally no content, these should not be hashed - if(!strlen($content) && $f->url==$feed->siteUrl) { - $f->urlContentHash = ""; + if (!strlen($content) && $f->url==$feed->siteUrl) { + $f->urlContentHash = ""; } else { $f->urlContentHash = hash('sha256', $f->url.$content); } // if the item's title is the same as its link URL, it has no title; if there is additionally no content, these should not be hashed - if(!strlen($content) && $f->title==$f->url) { + if (!strlen($content) && $f->title==$f->url) { $f->titleContentHash = ""; } else { $f->titleContentHash = hash('sha256', $f->title.$content); @@ -128,44 +129,44 @@ class Feed { // prefer an Atom ID as the item's ID $id = (string) $f->xml->children('http://www.w3.org/2005/Atom')->id; // otherwise use the RSS2 guid element - if(!strlen($id)) { + if (!strlen($id)) { $id = (string) $f->xml->guid; } // otherwise use the Dublin Core identifier element - if(!strlen($id)) { + if (!strlen($id)) { $id = (string) $f->xml->children('http://purl.org/dc/elements/1.1/')->identifier; } // otherwise there is no ID; if there is one, hash it - if(strlen($id)) { + if (strlen($id)) { $f->id = hash('sha256', $id); } // PicoFeed also doesn't gather up categories, so we do this as well $f->categories = []; // first add Atom categories - foreach($f->xml->children('http://www.w3.org/2005/Atom')->category as $c) { + foreach ($f->xml->children('http://www.w3.org/2005/Atom')->category as $c) { // if the category has a label, use that $name = (string) $c->attributes()->label; // otherwise use the term - if(!strlen($name)) { + if (!strlen($name)) { $name = (string) $c->attributes()->term; } // ... assuming it has that much - if(strlen($name)) { + if (strlen($name)) { $f->categories[] = $name; } } // next add RSS2 categories - foreach($f->xml->children()->category as $c) { + foreach ($f->xml->children()->category as $c) { $name = (string) $c; - if(strlen($name)) { + if (strlen($name)) { $f->categories[] = $name; } } // and finally try Dublin Core subjects - foreach($f->xml->children('http://purl.org/dc/elements/1.1/')->subject as $c) { + foreach ($f->xml->children('http://purl.org/dc/elements/1.1/')->subject as $c) { $name = (string) $c; - if(strlen($name)) { + if (strlen($name)) { $f->categories[] = $name; } } @@ -178,26 +179,26 @@ class Feed { protected function deduplicateItems(array $items): array { /* Rationale: - Some newsfeeds (notably Planet) include multiple versions of an + Some newsfeeds (notably Planet) include multiple versions of an item if it is updated. As we only care about the latest, we - try to remove any "old" versions of an item that might also be + try to remove any "old" versions of an item that might also be present within the feed. */ $out = []; - foreach($items as $item) { - foreach($out as $index => $check) { + foreach ($items as $item) { + foreach ($out as $index => $check) { // if the two items both have IDs and they differ, they do not match, regardless of hashes - if($item->id && $check->id && $item->id != $check->id) { + if ($item->id && $check->id && $item->id != $check->id) { continue; } // if the two items have the same ID or any one hash matches, they are two versions of the same item - if( + if ( ($item->id && $check->id && $item->id == $check->id) || ($item->urlTitleHash && $item->urlTitleHash == $check->urlTitleHash) || ($item->urlContentHash && $item->urlContentHash == $check->urlContentHash) || ($item->titleContentHash && $item->titleContentHash == $check->titleContentHash) ) { - 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 ($item->updatedDate && !$check->updatedDate) || // the later item has an update date newer than the existing item's @@ -224,7 +225,7 @@ class Feed { // first perform deduplication on items $items = $this->deduplicateItems($this->data->items); // if we haven't been given a database feed ID to check against, all items are new - if(is_null($feedID)) { + if (is_null($feedID)) { $this->newItems = $items; return true; } @@ -232,20 +233,20 @@ class Feed { $articles = Arsse::$db->feedMatchLatest($feedID, sizeof($items))->getAll(); // perform a first pass matching the latest articles against items in the feed list($this->newItems, $this->changedItems) = $this->matchItems($items, $articles); - if(sizeof($this->newItems) && sizeof($items) <= sizeof($articles)) { + if (sizeof($this->newItems) && sizeof($items) <= sizeof($articles)) { // if we need to, perform a second pass on the database looking specifically for IDs and hashes of the new items $ids = $hashesUT = $hashesUC = $hashesTC = []; - foreach($this->newItems as $i) { - if($i->id) { + foreach ($this->newItems as $i) { + if ($i->id) { $ids[] = $i->id; } - if($i->urlTitleHash) { + if ($i->urlTitleHash) { $hashesUT[] = $i->urlTitleHash; } - if($i->urlContentHash) { + if ($i->urlContentHash) { $hashesUC[] = $i->urlContentHash; } - if($i->titleContentHash) { + if ($i->titleContentHash) { $hashesTC[] = $i->titleContentHash; } } @@ -260,14 +261,14 @@ class Feed { protected function matchItems(array $items, array $articles): array { $new = $edited = []; // iterate through the articles and for each determine whether it is existing, edited, or entirely new - foreach($items as $i) { + foreach ($items as $i) { $found = false; - foreach($articles as $a) { + foreach ($articles as $a) { // if the item has an ID and it doesn't match the article ID, the two don't match, regardless of hashes - if($i->id && $i->id !== $a['guid']) { + if ($i->id && $i->id !== $a['guid']) { continue; } - if( + if ( // the item matches if the GUID matches... ($i->id && $i->id === $a['guid']) || // ... or if any one of the hashes match @@ -275,13 +276,13 @@ class Feed { ($i->urlContentHash && $i->urlContentHash === $a['url_content_hash']) || ($i->titleContentHash && $i->titleContentHash === $a['title_content_hash']) ) { - if($i->updatedDate && Date::transform($i->updatedDate, "sql") !== $a['edited']) { + if ($i->updatedDate && Date::transform($i->updatedDate, "sql") !== $a['edited']) { // if the item has an edit timestamp and it doesn't match that of the article in the database, the the article has been edited // we store the item index and database record ID as a key/value pair $found = true; $edited[$a['id']] = $i; break; - } else if($i->urlTitleHash !== $a['url_title_hash'] || $i->urlContentHash !== $a['url_content_hash'] || $i->titleContentHash !== $a['title_content_hash']) { + } elseif ($i->urlTitleHash !== $a['url_title_hash'] || $i->urlContentHash !== $a['url_content_hash'] || $i->titleContentHash !== $a['title_content_hash']) { // if any of the hashes do not match, then the article has been edited $found = true; $edited[$a['id']] = $i; @@ -293,7 +294,7 @@ class Feed { } } } - if(!$found) { + if (!$found) { $new[] = $i; } } @@ -302,7 +303,7 @@ class Feed { protected function computeNextFetch(): \DateTime { $now = Date::normalize(time()); - if(!$this->modified) { + if (!$this->modified) { $diff = $now->getTimestamp() - $this->lastModified->getTimestamp(); $offset = $this->normalizeDateDiff($diff); $now->modify("+".$offset); @@ -313,14 +314,14 @@ class Feed { // interval is "less than 30m"). If there is no commonality, the feed is checked in 1 hour. $offsets = []; $dates = $this->gatherDates(); - if(sizeof($dates) > 3) { - for($a = 0; $a < 3; $a++) { + if (sizeof($dates) > 3) { + for ($a = 0; $a < 3; $a++) { $diff = $dates[$a] - $dates[$a+1]; $offsets[] = $this->normalizeDateDiff($diff); } - if($offsets[0]==$offsets[1] || $offsets[0]==$offsets[2]) { + if ($offsets[0]==$offsets[1] || $offsets[0]==$offsets[2]) { $now->modify("+".$offsets[0]); - } else if($offsets[1]==$offsets[2]) { + } elseif ($offsets[1]==$offsets[2]) { $now->modify("+".$offsets[1]); } else { $now->modify("+ 1 hour"); @@ -333,9 +334,9 @@ class Feed { } public static function nextFetchOnError($errCount): \DateTime { - if($errCount < 3) { + if ($errCount < 3) { $offset = "5 minutes"; - } else if($errCount < 15) { + } elseif ($errCount < 15) { $offset = "3 hours"; } else { $offset = "1 day"; @@ -344,13 +345,13 @@ class Feed { } protected function normalizeDateDiff(int $diff): string { - if($diff < (30 * 60)) { // less than 30 minutes + if ($diff < (30 * 60)) { // less than 30 minutes $offset = "15 minutes"; - } else if($diff < (60 * 60)) { // less than an hour + } elseif ($diff < (60 * 60)) { // less than an hour $offset = "30 minutes"; - } else if($diff < (3 * 60 * 60)) { // less than three hours + } elseif ($diff < (3 * 60 * 60)) { // less than three hours $offset = "1 hour"; - } else if($diff >= (36 * 60 * 60)) { // more than 36 hours + } elseif ($diff >= (36 * 60 * 60)) { // more than 36 hours $offset = "1 day"; } else { $offset = "3 hours"; @@ -359,11 +360,11 @@ class Feed { } protected function computeLastModified() { - if(!$this->modified) { + if (!$this->modified) { return $this->lastModified; } $dates = $this->gatherDates(); - if(sizeof($dates)) { + if (sizeof($dates)) { return Date::normalize($dates[0]); } else { return null; @@ -372,11 +373,11 @@ class Feed { protected function gatherDates(): array { $dates = []; - foreach($this->data->items as $item) { - if($item->updatedDate) { + foreach ($this->data->items as $item) { + if ($item->updatedDate) { $dates[] = $item->updatedDate->getTimestamp(); } - if($item->publishedDate) { + if ($item->publishedDate) { $dates[] = $item->publishedDate->getTimestamp(); } } @@ -387,13 +388,13 @@ class Feed { protected function scrape(): bool { $scraper = new Scraper($this->config); - foreach(array_merge($this->newItems, $this->changedItems) as $item) { + foreach (array_merge($this->newItems, $this->changedItems) as $item) { $scraper->setUrl($item->url); $scraper->execute(); - if($scraper->hasRelevantContent()) { + if ($scraper->hasRelevantContent()) { $item->content = $scraper->getFilteredContent(); } } return true; } -} \ No newline at end of file +} diff --git a/lib/Feed/Exception.php b/lib/Feed/Exception.php index 7b5ccc6..79121a5 100644 --- a/lib/Feed/Exception.php +++ b/lib/Feed/Exception.php @@ -11,4 +11,4 @@ class Exception extends \JKingWeb\Arsse\AbstractException { $msgID = ($msgID !== $className) ? lcfirst($msgID) : ''; parent::__construct($msgID, ['url' => $url], $e); } -} \ No newline at end of file +} diff --git a/lib/Lang.php b/lib/Lang.php index e64a182..60411ca 100644 --- a/lib/Lang.php +++ b/lib/Lang.php @@ -16,34 +16,34 @@ class Lang { ]; public $path; // path to locale files; this is a public property to facilitate unit testing - static protected $requirementsMet = false; // whether the Intl extension is loaded + protected static $requirementsMet = false; // whether the Intl extension is loaded protected $synched = false; // whether the wanted locale is actually loaded (lazy loading is used by default) protected $wanted = self::DEFAULT; // the currently requested locale protected $locale = ""; // the currently loaded locale protected $loaded = []; // the cascade of loaded locale file names protected $strings = self::REQUIRED; // the loaded locale strings, merged - function __construct(string $path = BASE."locale".DIRECTORY_SEPARATOR) { + public function __construct(string $path = BASE."locale".DIRECTORY_SEPARATOR) { $this->path = $path; } public function set(string $locale, bool $immediate = false): string { // make sure the Intl extension is loaded - if(!static::$requirementsMet) { + if (!static::$requirementsMet) { static::checkRequirements(); } // if requesting the same locale as already wanted, just return (but load first if we've requested an immediate load) - if($locale==$this->wanted) { - if($immediate && !$this->synched) { + if ($locale==$this->wanted) { + if ($immediate && !$this->synched) { $this->load(); } return $locale; } // if we've requested a locale other than the null locale, fetch the list of available files and find the closest match e.g. en_ca_somedialect -> en_ca - if($locale != "") { + if ($locale != "") { $list = $this->listFiles(); // if the default locale is unavailable, this is (for now) an error - if(!in_array(self::DEFAULT, $list)) { + if (!in_array(self::DEFAULT, $list)) { throw new Lang\Exception("defaultFileMissing", self::DEFAULT); } $this->wanted = $this->match($locale, $list); @@ -52,7 +52,7 @@ class Lang { } $this->synched = false; // load right now if asked to, otherwise load later when actually required - if($immediate) { + if ($immediate) { $this->load(); } return $this->wanted; @@ -73,29 +73,33 @@ class Lang { public function __invoke(string $msgID, $vars = null): string { // if we're trying to load the system default language and it fails, we have a chicken and egg problem, so we catch the exception and load no language file instead - if(!$this->synched) try {$this->load();} catch(Lang\Exception $e) { - if($this->wanted==self::DEFAULT) { - $this->set("", true); - } else { - throw $e; + if (!$this->synched) { + try { + $this->load(); + } catch (Lang\Exception $e) { + if ($this->wanted==self::DEFAULT) { + $this->set("", true); + } else { + throw $e; + } } } // if the requested message is not present in any of the currently loaded language files, throw an exception // note that this is indicative of a programming error since the default locale should have all strings - if(!array_key_exists($msgID, $this->strings)) { - throw new Lang\Exception("stringMissing", ['msgID' => $msgID, 'fileList' => implode(", ",$this->loaded)]); + if (!array_key_exists($msgID, $this->strings)) { + throw new Lang\Exception("stringMissing", ['msgID' => $msgID, 'fileList' => implode(", ", $this->loaded)]); } $msg = $this->strings[$msgID]; // variables fed to MessageFormatter must be contained in an array - if($vars===null) { + if ($vars===null) { // even though strings not given parameters will not get formatted, we do not optimize this case away: we still want to catch invalid strings $vars = []; - } else if(!is_array($vars)) { + } elseif (!is_array($vars)) { $vars = [$vars]; } $msg = \MessageFormatter::formatMessage($this->locale, $msg, $vars); - if($msg===false) { - throw new Lang\Exception("stringInvalid", ['msgID' => $msgID, 'fileList' => implode(", ",$this->loaded)]); + if ($msg===false) { + throw new Lang\Exception("stringInvalid", ['msgID' => $msgID, 'fileList' => implode(", ", $this->loaded)]); } return $msg; } @@ -103,22 +107,22 @@ class Lang { public function list(string $locale = ""): array { $out = []; $files = $this->listFiles(); - foreach($files as $tag) { + foreach ($files as $tag) { $out[$tag] = \Locale::getDisplayName($tag, ($locale=="") ? $tag : $locale); } return $out; } public function match(string $locale, array $list = null): string { - if($list===null) { + if ($list===null) { $list = $this->listFiles(); } $default = ($this->locale=="") ? self::DEFAULT : $this->locale; - return \Locale::lookup($list,$locale, true, $default); + return \Locale::lookup($list, $locale, true, $default); } - static protected function checkRequirements(): bool { - if(!extension_loaded("intl")) { + protected static function checkRequirements(): bool { + if (!extension_loaded("intl")) { throw new ExceptionFatal("The \"Intl\" extension is required, but not loaded"); } static::$requirementsMet = true; @@ -133,22 +137,22 @@ class Lang { protected function listFiles(): array { $out = $this->globFiles($this->path."*.php"); // trim the returned file paths to return just the language tag - $out = array_map(function($file) { + $out = array_map(function ($file) { $file = str_replace(DIRECTORY_SEPARATOR, "/", $file); // we replace the directory separator because we don't use native paths in testing $file = substr($file, strrpos($file, "/")+1); - return strtolower(substr($file,0,strrpos($file,"."))); - },$out); + return strtolower(substr($file, 0, strrpos($file, "."))); + }, $out); // sort the results natsort($out); return $out; } protected function load(): bool { - if(!self::$requirementsMet) { + if (!self::$requirementsMet) { self::checkRequirements(); } // if we've requested no locale (""), just load the fallback strings and return - if($this->wanted=="") { + if ($this->wanted=="") { $this->strings = self::REQUIRED; $this->locale = $this->wanted; $this->synched = true; @@ -157,27 +161,27 @@ class Lang { // decompose the requested locale from specific to general, building a list of files to load $tags = \Locale::parseLocale($this->wanted); $files = []; - while(sizeof($tags) > 0) { + while (sizeof($tags) > 0) { $files[] = strtolower(\Locale::composeLocale($tags)); $tag = array_pop($tags); } // include the default locale as the base if the most general locale requested is not the default - if($tag != self::DEFAULT) { + if ($tag != self::DEFAULT) { $files[] = self::DEFAULT; } // save the list of files to be loaded for later reference $loaded = $files; // reduce the list of files to be loaded to the minimum necessary (e.g. if we go from "fr" to "fr_ca", we don't need to load "fr" or "en") $files = []; - foreach($loaded as $file) { - if($file==$this->locale) { + foreach ($loaded as $file) { + if ($file==$this->locale) { break; } $files[] = $file; } // if we need to load all files, start with the fallback strings $strings = []; - if($files==$loaded) { + if ($files==$loaded) { $strings[] = self::REQUIRED; } else { // otherwise start with the strings we already have if we're going from e.g. "fr" to "fr_ca" @@ -185,22 +189,22 @@ class Lang { } // read files in reverse order $files = array_reverse($files); - foreach($files as $file) { - if(!file_exists($this->path."$file.php")) { + foreach ($files as $file) { + if (!file_exists($this->path."$file.php")) { throw new Lang\Exception("fileMissing", $file); - } else if(!is_readable($this->path."$file.php")) { + } elseif (!is_readable($this->path."$file.php")) { throw new Lang\Exception("fileUnreadable", $file); } try { // we use output buffering in case the language file is corrupted ob_start(); $arr = (include $this->path."$file.php"); - } catch(\Throwable $e) { + } catch (\Throwable $e) { $arr = null; } finally { ob_end_clean(); } - if(!is_array($arr)) { + if (!is_array($arr)) { throw new Lang\Exception("fileCorrupt", $file); } $strings[] = $arr; @@ -212,4 +216,4 @@ class Lang { $this->synched = true; return true; } -} \ No newline at end of file +} diff --git a/lib/Lang/Exception.php b/lib/Lang/Exception.php index 5340437..ad98877 100644 --- a/lib/Lang/Exception.php +++ b/lib/Lang/Exception.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Lang; class Exception extends \JKingWeb\Arsse\AbstractException { -} \ No newline at end of file +} diff --git a/lib/Misc/Context.php b/lib/Misc/Context.php index a52105e..d64a18f 100644 --- a/lib/Misc/Context.php +++ b/lib/Misc/Context.php @@ -1,9 +1,10 @@ props[$prop] = true; $this->$prop = $value; return $this; @@ -34,17 +35,17 @@ class Context { protected function cleanArray(array $spec): array { $spec = array_values($spec); - for($a = 0; $a < sizeof($spec); $a++) { + for ($a = 0; $a < sizeof($spec); $a++) { $id = $spec[$a]; - if(is_int($id) && $id > -1) { + if (is_int($id) && $id > -1) { continue; - } else if(is_float($id) && !fmod($id, 1) && $id >= 0) { + } elseif (is_float($id) && !fmod($id, 1) && $id >= 0) { $spec[$a] = (int) $id; continue; - } else if(is_string($id)) { + } elseif (is_string($id)) { $ch1 = strval(@intval($id)); $ch2 = strval($id); - if($ch1 !== $ch2 || $id < 1) { + if ($ch1 !== $ch2 || $id < 1) { $id = 0; } } else { @@ -55,71 +56,71 @@ class Context { return array_values(array_filter($spec)); } - function reverse(bool $spec = null) { + public function reverse(bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function limit(int $spec = null) { + public function limit(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function offset(int $spec = null) { + public function offset(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function folder(int $spec = null) { + public function folder(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function subscription(int $spec = null) { + public function subscription(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function latestEdition(int $spec = null) { + public function latestEdition(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function oldestEdition(int $spec = null) { + public function oldestEdition(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function unread(bool $spec = null) { + public function unread(bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function starred(bool $spec = null) { + public function starred(bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function modifiedSince($spec = null) { + public function modifiedSince($spec = null) { $spec = Date::normalize($spec); return $this->act(__FUNCTION__, func_num_args(), $spec); } - function notModifiedSince($spec = null) { + public function notModifiedSince($spec = null) { $spec = Date::normalize($spec); return $this->act(__FUNCTION__, func_num_args(), $spec); } - function edition(int $spec = null) { + public function edition(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function article(int $spec = null) { + public function article(int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - function editions(array $spec = null) { - if($spec) { + public function editions(array $spec = null) { + if ($spec) { $spec = $this->cleanArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - function articles(array $spec = null) { - if($spec) { + public function articles(array $spec = null) { + if ($spec) { $spec = $this->cleanArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } -} \ No newline at end of file +} diff --git a/lib/Misc/Date.php b/lib/Misc/Date.php index eaf70b5..f1755cf 100644 --- a/lib/Misc/Date.php +++ b/lib/Misc/Date.php @@ -3,14 +3,13 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Misc; class Date { - - static function transform($date, string $outFormat = null, string $inFormat = null, bool $inLocal = false) { + public static function transform($date, string $outFormat = null, string $inFormat = null, bool $inLocal = false) { $date = self::normalize($date, $inFormat, $inLocal); - if(is_null($date) || is_null($outFormat)) { + if (is_null($date) || is_null($outFormat)) { return $date; } $outFormat = strtolower($outFormat); - if($outFormat=="unix") { + if ($outFormat=="unix") { return $date->getTimestamp(); } switch ($outFormat) { @@ -24,18 +23,18 @@ class Date { return $date->format($f); } - static function normalize($date, string $inFormat = null, bool $inLocal = false) { - if($date instanceof \DateTimeInterface) { + public static function normalize($date, string $inFormat = null, bool $inLocal = false) { + if ($date instanceof \DateTimeInterface) { return $date; - } else if(is_numeric($date)) { + } elseif (is_numeric($date)) { $time = (int) $date; - } else if($date===null) { + } elseif ($date===null) { return null; - } else if(is_string($date)) { + } elseif (is_string($date)) { try { $tz = (!$inLocal) ? new \DateTimeZone("UTC") : null; - if(!is_null($inFormat)) { - switch($inFormat) { + if (!is_null($inFormat)) { + switch ($inFormat) { case 'http': $f = "D, d M Y H:i:s \G\M\T"; break; case 'iso8601': $f = "Y-m-d\TH:i:sP"; break; case 'sql': $f = "Y-m-d H:i:s"; break; @@ -47,10 +46,10 @@ class Date { } else { return new \DateTime($date, $tz); } - } catch(\Throwable $e) { + } catch (\Throwable $e) { return null; } - } else if (is_bool($date)) { + } elseif (is_bool($date)) { return null; } else { $time = (int) $date; @@ -61,21 +60,21 @@ class Date { return $d; } - static function add(string $interval, $date = null): \DateTimeInterface { + public static function add(string $interval, $date = null): \DateTimeInterface { return self::modify("add", $interval, $date); } - static function sub(string $interval, $date = null): \DateTimeInterface { + public static function sub(string $interval, $date = null): \DateTimeInterface { return self::modify("sub", $interval, $date); } - static protected function modify(string $func, string $interval, $date = null): \DateTimeInterface { + protected static function modify(string $func, string $interval, $date = null): \DateTimeInterface { $date = self::normalize($date ?? time()); - if($date instanceof \DateTimeImmutable) { + if ($date instanceof \DateTimeImmutable) { return $date->$func(new \DateInterval($interval)); } else { $date->$func(new \DateInterval($interval)); return $date; } } -} \ No newline at end of file +} diff --git a/lib/Misc/Query.php b/lib/Misc/Query.php index 1bd3dd1..b480d3b 100644 --- a/lib/Misc/Query.php +++ b/lib/Misc/Query.php @@ -18,42 +18,42 @@ class Query { protected $offset = 0; - function __construct(string $body = "", $types = null, $values = null) { + public function __construct(string $body = "", $types = null, $values = null) { $this->setBody($body, $types, $values); } - function setBody(string $body = "", $types = null, $values = null): bool { + public function setBody(string $body = "", $types = null, $values = null): bool { $this->qBody = $body; - if(!is_null($types)) { + if (!is_null($types)) { $this->tBody[] = $types; $this->vBody[] = $values; } return true; } - function setCTE(string $tableSpec, string $body, $types = null, $values = null, string $join = ''): bool { + public function setCTE(string $tableSpec, string $body, $types = null, $values = null, string $join = ''): bool { $this->qCTE[] = "$tableSpec as ($body)"; - if(!is_null($types)) { + if (!is_null($types)) { $this->tCTE[] = $types; $this->vCTE[] = $values; } - if(strlen($join)) { // the CTE might only participate in subqueries rather than a join on the main query + if (strlen($join)) { // the CTE might only participate in subqueries rather than a join on the main query $this->jCTE[] = $join; } return true; } - function setWhere(string $where, $types = null, $values = null): bool { + public function setWhere(string $where, $types = null, $values = null): bool { $this->qWhere[] = $where; - if(!is_null($types)) { + if (!is_null($types)) { $this->tWhere[] = $types; $this->vWhere[] = $values; } return true; } - function setOrder(string $order, bool $prepend = false): bool { - if($prepend) { + public function setOrder(string $order, bool $prepend = false): bool { + if ($prepend) { array_unshift($this->order, $order); } else { $this->order[] = $order; @@ -61,13 +61,13 @@ class Query { return true; } - function setLimit(int $limit, int $offset = 0): bool { + public function setLimit(int $limit, int $offset = 0): bool { $this->limit = $limit; $this->offset = $offset; return true; } - function pushCTE(string $tableSpec, string $join = ''): bool { + public function pushCTE(string $tableSpec, string $join = ''): bool { // this function takes the query body and converts it to a common table expression, putting it at the bottom of the existing CTE stack // all WHERE, ORDER BY, and LIMIT parts belong to the new CTE and are removed from the main query $this->setCTE($tableSpec, $this->buildQueryBody(), [$this->tBody, $this->tWhere], [$this->vBody, $this->vWhere]); @@ -78,16 +78,16 @@ class Query { $this->tWhere = []; $this->vWhere = []; $this->order = []; - $this->setLimit(0,0); - if(strlen($join)) { + $this->setLimit(0, 0); + if (strlen($join)) { $this->jCTE[] = $join; } return true; } - function __toString(): string { + public function __toString(): string { $out = ""; - if(sizeof($this->qCTE)) { + if (sizeof($this->qCTE)) { // start with common table expressions $out .= "WITH RECURSIVE ".implode(", ", $this->qCTE)." "; } @@ -96,31 +96,31 @@ class Query { return $out; } - function getQuery(): string { + public function getQuery(): string { return $this->__toString(); } - function getTypes(): array { + public function getTypes(): array { return [$this->tCTE, $this->tBody, $this->tWhere]; } - function getValues(): array { + public function getValues(): array { return [$this->vCTE, $this->vBody, $this->vWhere]; } - function getWhereTypes(): array { + public function getWhereTypes(): array { return $this->tWhere; } - function getWhereValues(): array { + public function getWhereValues(): array { return $this->vWhere; } - function getCTETypes(): array { + public function getCTETypes(): array { return $this->tCTE; } - function getCTEValues(): array { + public function getCTEValues(): array { return $this->vCTE; } @@ -128,25 +128,25 @@ class Query { $out = ""; // add the body $out .= $this->qBody; - if(sizeof($this->qCTE)) { + if (sizeof($this->qCTE)) { // add any joins against CTEs $out .= " ".implode(" ", $this->jCTE); } // add any WHERE terms - if(sizeof($this->qWhere)) { + if (sizeof($this->qWhere)) { $out .= " WHERE ".implode(" AND ", $this->qWhere); } // add any ORDER BY terms - if(sizeof($this->order)) { + if (sizeof($this->order)) { $out .= " ORDER BY ".implode(", ", $this->order); } // add LIMIT and OFFSET if the former is specified - if($this->limit > 0) { + if ($this->limit > 0) { $out .= " LIMIT ".$this->limit; - if($this->offset > 0) { + if ($this->offset > 0) { $out .= " OFFSET ".$this->offset; } } return $out; } -} \ No newline at end of file +} diff --git a/lib/REST.php b/lib/REST.php index 980a1bb..68f5e0b 100644 --- a/lib/REST.php +++ b/lib/REST.php @@ -27,31 +27,33 @@ class REST { // CommaFeed https://www.commafeed.com/api/ ]; - function __construct() { + public function __construct() { } - function dispatch(REST\Request $req = null): REST\Response { - if($req===null) { + public function dispatch(REST\Request $req = null): REST\Response { + if ($req===null) { $req = new REST\Request(); } $api = $this->apiMatch($req->url, $this->apis); - $req->url = substr($req->url,strlen($this->apis[$api]['strip'])); + $req->url = substr($req->url, strlen($this->apis[$api]['strip'])); $req->refreshURL(); $class = $this->apis[$api]['class']; $drv = new $class(); return $drv->dispatch($req); } - function apiMatch(string $url, array $map): string { + public function apiMatch(string $url, array $map): string { // sort the API list so the longest URL prefixes come first - uasort($map, function($a, $b) {return (strlen($a['match']) <=> strlen($b['match'])) * -1;}); + uasort($map, function ($a, $b) { + return (strlen($a['match']) <=> strlen($b['match'])) * -1; + }); // find a match - foreach($map as $id => $api) { - if(strpos($url, $api['match'])===0) { + foreach ($map as $id => $api) { + if (strpos($url, $api['match'])===0) { return $id; } } // or throw an exception otherwise throw new REST\Exception501(); } -} \ No newline at end of file +} diff --git a/lib/REST/AbstractHandler.php b/lib/REST/AbstractHandler.php index a39bbb6..d2994b7 100644 --- a/lib/REST/AbstractHandler.php +++ b/lib/REST/AbstractHandler.php @@ -1,27 +1,27 @@ $from) { - if(array_key_exists($from, $data)) { + foreach ($map as $to => $from) { + if (array_key_exists($from, $data)) { $out[$to] = $data[$from]; } } return $out; - } + } protected function fieldMapTypes(array $data, array $map, string $dateFormat = "sql"): array { - foreach($map as $key => $type) { - if(array_key_exists($key, $data)) { - if($type=="datetime" && $dateFormat != "sql") { + foreach ($map as $key => $type) { + if (array_key_exists($key, $data)) { + if ($type=="datetime" && $dateFormat != "sql") { $data[$key] = Date::transform($data[$key], $dateFormat, "sql"); } else { settype($data[$key], $type); @@ -39,18 +39,18 @@ abstract class AbstractHandler implements Handler { protected function NormalizeInput(array $data, array $types, string $dateFormat = null): array { $out = []; - foreach($data as $key => $value) { - if(!isset($types[$key])) { + foreach ($data as $key => $value) { + if (!isset($types[$key])) { $out[$key] = $value; continue; } - if(is_null($value)) { + if (is_null($value)) { $out[$key] = null; continue; } - switch($types[$key]) { + switch ($types[$key]) { case "int": - if($this->validateInt($value)) { + if ($this->validateInt($value)) { $out[$key] = (int) $value; } break; @@ -58,31 +58,31 @@ abstract class AbstractHandler implements Handler { $out[$key] = (string) $value; break; case "bool": - if(is_bool($value)) { + if (is_bool($value)) { $out[$key] = $value; - } else if($this->validateInt($value)) { + } elseif ($this->validateInt($value)) { $value = (int) $value; - if($value > -1 && $value < 2) { + if ($value > -1 && $value < 2) { $out[$key] = $value; } - } else if(is_string($value)) { + } elseif (is_string($value)) { $value = trim(strtolower($value)); - if($value=="false") { + if ($value=="false") { $out[$key] = false; } - if($value=="true") { + if ($value=="true") { $out[$key] = true; } } break; case "float": - if(is_numeric($value)) { + if (is_numeric($value)) { $out[$key] = (float) $value; } break; case "datetime": $t = Date::normalize($value, $dateFormat); - if($t) { + if ($t) { $out[$key] = $t; } break; @@ -92,4 +92,4 @@ abstract class AbstractHandler implements Handler { } return $out; } -} \ No newline at end of file +} diff --git a/lib/REST/Exception.php b/lib/REST/Exception.php index 308621e..601ad06 100644 --- a/lib/REST/Exception.php +++ b/lib/REST/Exception.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\REST; class Exception extends \JKingWeb\Arsse\AbstractException { -} \ No newline at end of file +} diff --git a/lib/REST/Exception405.php b/lib/REST/Exception405.php index 8c1f148..ed78c4d 100644 --- a/lib/REST/Exception405.php +++ b/lib/REST/Exception405.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\REST; class Exception405 extends \Exception { -} \ No newline at end of file +} diff --git a/lib/REST/Exception501.php b/lib/REST/Exception501.php index 879a73c..31a7abc 100644 --- a/lib/REST/Exception501.php +++ b/lib/REST/Exception501.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\REST; class Exception501 extends \Exception { -} \ No newline at end of file +} diff --git a/lib/REST/Handler.php b/lib/REST/Handler.php index 6ac7290..023528f 100644 --- a/lib/REST/Handler.php +++ b/lib/REST/Handler.php @@ -3,6 +3,6 @@ declare(strict_types=1); namespace JKingWeb\Arsse\REST; interface Handler { - function __construct(); - function dispatch(Request $req): Response; -} \ No newline at end of file + public function __construct(); + public function dispatch(Request $req): Response; +} diff --git a/lib/REST/NextCloudNews/V1_2.php b/lib/REST/NextCloudNews/V1_2.php index cf1d686..fdcc8a7 100644 --- a/lib/REST/NextCloudNews/V1_2.php +++ b/lib/REST/NextCloudNews/V1_2.php @@ -1,6 +1,7 @@ "array int", // just pass these through ]; - function __construct() { + public function __construct() { } - function dispatch(\JKingWeb\Arsse\REST\Request $req): Response { + public function dispatch(\JKingWeb\Arsse\REST\Request $req): Response { // try to authenticate - if(!Arsse::$user->authHTTP()) { + if (!Arsse::$user->authHTTP()) { return new Response(401, "", "", ['WWW-Authenticate: Basic realm="'.self::REALM.'"']); } // normalize the input - if($req->body) { + if ($req->body) { // if the entity body is not JSON according to content type, return "415 Unsupported Media Type" - if(!preg_match("<^application/json\b|^$>", $req->type)) { + if (!preg_match("<^application/json\b|^$>", $req->type)) { return new Response(415, "", "", ['Accept: application/json']); } $data = @json_decode($req->body, true); - if(json_last_error() != \JSON_ERROR_NONE) { + if (json_last_error() != \JSON_ERROR_NONE) { // if the body could not be parsed as JSON, return "400 Bad Request" return new Response(400); } @@ -66,21 +67,21 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // check to make sure the requested function is implemented try { $func = $this->chooseCall($req->paths, $req->method); - } catch(Exception501 $e) { + } catch (Exception501 $e) { return new Response(501); - } catch(Exception405 $e) { + } catch (Exception405 $e) { return new Response(405, "", "", ["Allow: ".$e->getMessage()]); } - if(!method_exists($this, $func)) { + if (!method_exists($this, $func)) { return new Response(501); } // dispatch try { return $this->$func($req->paths, $data); - } catch(Exception $e) { + } catch (Exception $e) { // if there was a REST exception return 400 return new Response(400); - } catch(AbstractException $e) { + } catch (AbstractException $e) { // if there was any other Arsse exception return 500 return new Response(500); } @@ -133,27 +134,27 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // the first path element is the overall scope of the request $scope = $url[0]; // any URL components which are only digits should be replaced with "0", for easier comparison (integer segments are IDs, and we don't care about the specific ID) - for($a = 0; $a < sizeof($url); $a++) { - if($this->validateInt($url[$a])) { + for ($a = 0; $a < sizeof($url); $a++) { + if ($this->validateInt($url[$a])) { $url[$a] = "0"; } } // normalize the HTTP method to uppercase $method = strtoupper($method); // if the scope is not supported, return 501 - if(!array_key_exists($scope, $choices)) { + if (!array_key_exists($scope, $choices)) { throw new Exception501(); } // we now evaluate the supplied URL against every supported path for the selected scope // the URL is evaluated as an array so as to avoid decoded escapes turning invalid URLs into valid ones - foreach($choices[$scope] as $path => $funcs) { + foreach ($choices[$scope] as $path => $funcs) { // add the scope to the path to match against and split it $path = (string) $path; $path = (strlen($path)) ? "$scope/$path" : $scope; $path = explode("/", $path); - if($path===$url) { + if ($path===$url) { // if the path matches, make sure the method is allowed - if(array_key_exists($method,$funcs)) { + if (array_key_exists($method, $funcs)) { // if it is allowed, return the object method to run return $funcs[$method]; } else { @@ -230,8 +231,8 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { protected function folderAdd(array $url, array $data): Response { try { $folder = Arsse::$db->folderAdd(Arsse::$user->id, $data); - } catch(ExceptionInput $e) { - switch($e->getCode()) { + } catch (ExceptionInput $e) { + switch ($e->getCode()) { // folder already exists case 10236: return new Response(409); // folder name not acceptable @@ -250,7 +251,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // perform the deletion try { Arsse::$db->folderRemove(Arsse::$user->id, (int) $url[1]); - } catch(ExceptionInput $e) { + } catch (ExceptionInput $e) { // folder does not exist return new Response(404); } @@ -260,14 +261,14 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // rename a folder (also supports moving nesting folders, but this is not a feature of the API) protected function folderRename(array $url, array $data): Response { // there must be some change to be made - if(!sizeof($data)) { + if (!sizeof($data)) { return new Response(422); } // perform the edit try { Arsse::$db->folderPropertiesSet(Arsse::$user->id, (int) $url[1], $data); - } catch(ExceptionInput $e) { - switch($e->getCode()) { + } catch (ExceptionInput $e) { + switch ($e->getCode()) { // folder does not exist case 10239: return new Response(404); // folder already exists @@ -285,7 +286,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // mark all articles associated with a folder as read protected function folderMarkRead(array $url, array $data): Response { $c = new Context; - if(isset($data['newestItemId'])) { + if (isset($data['newestItemId'])) { // if the item ID is valid (i.e. an integer), add it to the context $c->latestEdition($data['newestItemId']); } else { @@ -297,7 +298,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // perform the operation try { Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c); - } catch(ExceptionInput $e) { + } catch (ExceptionInput $e) { // folder does not exist return new Response(404); } @@ -307,13 +308,13 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // return list of feeds which should be refreshed protected function feedListStale(array $url, array $data): Response { // function requires admin rights per spec - if(Arsse::$user->rightsGet(Arsse::$user->id)==User::RIGHTS_NONE) { + if (Arsse::$user->rightsGet(Arsse::$user->id)==User::RIGHTS_NONE) { return new Response(403); } // list stale feeds which should be checked for updates $feeds = Arsse::$db->feedListStale(); $out = []; - foreach($feeds as $feed) { + foreach ($feeds as $feed) { // since in our implementation feeds don't belong the users, the 'userId' field will always be an empty string $out[] = ['id' => $feed, 'userId' => ""]; } @@ -323,16 +324,16 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // refresh a feed protected function feedUpdate(array $url, array $data): Response { // function requires admin rights per spec - if(Arsse::$user->rightsGet(Arsse::$user->id)==User::RIGHTS_NONE) { + if (Arsse::$user->rightsGet(Arsse::$user->id)==User::RIGHTS_NONE) { return new Response(403); } // perform an update of a single feed - if(!isset($data['feedId'])) { + if (!isset($data['feedId'])) { return new Response(422); } try { Arsse::$db->feedUpdate($data['feedId']); - } catch(ExceptionInput $e) { + } catch (ExceptionInput $e) { return new Response(404); } return new Response(204); @@ -341,7 +342,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // add a new feed protected function subscriptionAdd(array $url, array $data): Response { // normalize the feed URL - if(!isset($data['url'])) { + if (!isset($data['url'])) { return new Response(422); } // normalize the folder ID, if specified; zero should be transformed to null @@ -350,18 +351,19 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { $tr = Arsse::$db->begin(); try { $id = Arsse::$db->subscriptionAdd(Arsse::$user->id, $data['url']); - } catch(ExceptionInput $e) { + } catch (ExceptionInput $e) { // feed already exists return new Response(409); - } catch(FeedException $e) { + } catch (FeedException $e) { // feed could not be retrieved return new Response(422); } // if a folder was specified, move the feed to the correct folder; silently ignore errors - if($folder) { + if ($folder) { try { Arsse::$db->subscriptionPropertiesSet(Arsse::$user->id, $id, ['folder' => $folder]); - } catch(ExceptionInput $e) {} + } catch (ExceptionInput $e) { + } } $tr->commit(); // fetch the feed's metadata and format it appropriately @@ -369,7 +371,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { $feed = $this->feedTranslate($feed); $out = ['feeds' => [$feed]]; $newest = Arsse::$db->editionLatest(Arsse::$user->id, (new Context)->subscription($id)); - if($newest) { + if ($newest) { $out['newestItemId'] = $newest; } return new Response(200, $out); @@ -379,13 +381,13 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { protected function subscriptionList(array $url, array $data): Response { $subs = Arsse::$db->subscriptionList(Arsse::$user->id); $out = []; - foreach($subs as $sub) { + foreach ($subs as $sub) { $out[] = $this->feedTranslate($sub); } $out = ['feeds' => $out]; $out['starredCount'] = Arsse::$db->articleStarredCount(Arsse::$user->id); $newest = Arsse::$db->editionLatest(Arsse::$user->id); - if($newest) { + if ($newest) { $out['newestItemId'] = $newest; } return new Response(200, $out); @@ -395,7 +397,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { protected function subscriptionRemove(array $url, array $data): Response { try { Arsse::$db->subscriptionRemove(Arsse::$user->id, (int) $url[1]); - } catch(ExceptionInput $e) { + } catch (ExceptionInput $e) { // feed does not exist return new Response(404); } @@ -406,7 +408,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { protected function subscriptionRename(array $url, array $data): Response { // normalize input $in = []; - if(array_key_exists('feedTitle', $data)) { // we use array_key_exists because null is a valid input + if (array_key_exists('feedTitle', $data)) { // we use array_key_exists because null is a valid input $in['title'] = $data['feedTitle']; } else { return new Response(422); @@ -414,8 +416,8 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // perform the renaming try { Arsse::$db->subscriptionPropertiesSet(Arsse::$user->id, (int) $url[1], $in); - } catch(ExceptionInput $e) { - switch($e->getCode()) { + } catch (ExceptionInput $e) { + switch ($e->getCode()) { // subscription does not exist case 10239: return new Response(404); // name is invalid @@ -432,7 +434,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { protected function subscriptionMove(array $url, array $data): Response { // normalize input $in = []; - if(isset($data['folderId'])) { + if (isset($data['folderId'])) { $in['folder'] = $data['folderId'] ? $data['folderId'] : null; } else { return new Response(422); @@ -440,8 +442,8 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // perform the move try { Arsse::$db->subscriptionPropertiesSet(Arsse::$user->id, (int) $url[1], $in); - } catch(ExceptionInput $e) { - switch($e->getCode()) { + } catch (ExceptionInput $e) { + switch ($e->getCode()) { // subscription does not exist case 10239: return new Response(404); // folder does not exist @@ -456,7 +458,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // mark all articles associated with a subscription as read protected function subscriptionMarkRead(array $url, array $data): Response { $c = new Context; - if(isset($data['newestItemId'])) { + if (isset($data['newestItemId'])) { $c->latestEdition($data['newestItemId']); } else { // otherwise return an error @@ -467,7 +469,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // perform the operation try { Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c); - } catch(ExceptionInput $e) { + } catch (ExceptionInput $e) { // subscription does not exist return new Response(404); } @@ -479,39 +481,39 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // set the context options supplied by the client $c = new Context; // set the batch size - if(isset($data['batchSize']) && $data['batchSize'] > 0) { + if (isset($data['batchSize']) && $data['batchSize'] > 0) { $c->limit($data['batchSize']); } // set the order of returned items - if(isset($data['oldestFirst']) && $data['oldestFirst']) { + if (isset($data['oldestFirst']) && $data['oldestFirst']) { $c->reverse(false); } else { $c->reverse(true); } // set the edition mark-off; the database uses an or-equal comparison for internal consistency, but the protocol does not, so we must adjust by one - if(isset($data['offset']) && $data['offset'] > 0) { - if($c->reverse) { + if (isset($data['offset']) && $data['offset'] > 0) { + if ($c->reverse) { $c->latestEdition($data['offset'] - 1); } else { $c->oldestEdition($data['offset'] + 1); } } // set whether to only return unread - if(isset($data['getRead']) && !$data['getRead']) { + if (isset($data['getRead']) && !$data['getRead']) { $c->unread(true); } // if no type is specified assume 3 (All) - if(!isset($data['type'])) { + if (!isset($data['type'])) { $data['type'] = 3; } - switch($data['type']) { + switch ($data['type']) { case 0: // feed - if(isset($data['id'])) { + if (isset($data['id'])) { $c->subscription($data['id']); } break; case 1: // folder - if(isset($data['id'])) { + if (isset($data['id'])) { $c->folder($data['id']); } break; @@ -522,18 +524,18 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // return all items } // whether to return only updated items - if(isset($data['lastModified'])) { + if (isset($data['lastModified'])) { $c->modifiedSince($data['lastModified']); } // perform the fetch try { $items = Arsse::$db->articleList(Arsse::$user->id, $c); - } catch(ExceptionInput $e) { + } catch (ExceptionInput $e) { // ID of subscription or folder is not valid return new Response(422); } $out = []; - foreach($items as $item) { + foreach ($items as $item) { $out[] = $this->articleTranslate($item); } $out = ['items' => $out]; @@ -543,7 +545,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // mark all articles as read protected function articleMarkReadAll(array $url, array $data): Response { $c = new Context; - if(isset($data['newestItemId'])) { + if (isset($data['newestItemId'])) { // set the newest item ID as specified $c->latestEdition($data['newestItemId']); } else { @@ -564,7 +566,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { $set = ($url[2]=="read"); try { Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c); - } catch(ExceptionInput $e) { + } catch (ExceptionInput $e) { // ID is not valid return new Response(404); } @@ -580,7 +582,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { $set = ($url[3]=="star"); try { Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c); - } catch(ExceptionInput $e) { + } catch (ExceptionInput $e) { // ID is not valid return new Response(404); } @@ -592,19 +594,20 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // determine whether to mark read or unread $set = ($url[1]=="read"); // if the input data is not at all valid, return an error - if(!isset($data['items']) || !is_array($data['items'])) { + if (!isset($data['items']) || !is_array($data['items'])) { return new Response(422); } // start a transaction and loop through the items $t = Arsse::$db->begin(); $in = array_chunk($data['items'], 50); - for($a = 0; $a < sizeof($in); $a++) { + for ($a = 0; $a < sizeof($in); $a++) { // initialize the matching context $c = new Context; $c->editions($in[$a]); try { Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c); - } catch(ExceptionInput $e) {} + } catch (ExceptionInput $e) { + } } $t->commit(); return new Response(204); @@ -615,19 +618,20 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // determine whether to mark starred or unstarred $set = ($url[1]=="star"); // if the input data is not at all valid, return an error - if(!isset($data['items']) || !is_array($data['items'])) { + if (!isset($data['items']) || !is_array($data['items'])) { return new Response(422); } // start a transaction and loop through the items $t = Arsse::$db->begin(); $in = array_chunk(array_column($data['items'], "guidHash"), 50); - for($a = 0; $a < sizeof($in); $a++) { + for ($a = 0; $a < sizeof($in); $a++) { // initialize the matching context $c = new Context; $c->articles($in[$a]); try { Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c); - } catch(ExceptionInput $e) {} + } catch (ExceptionInput $e) { + } } $t->commit(); return new Response(204); @@ -636,7 +640,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { protected function userStatus(array $url, array $data): Response { $data = Arsse::$user->propertiesGet(Arsse::$user->id, true); // construct the avatar structure, if an image is available - if(isset($data['avatar'])) { + if (isset($data['avatar'])) { $avatar = [ 'data' => base64_encode($data['avatar']['data']), 'mime' => $data['avatar']['type'], @@ -656,7 +660,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { protected function cleanupBefore(array $url, array $data): Response { // function requires admin rights per spec - if(Arsse::$user->rightsGet(Arsse::$user->id)==User::RIGHTS_NONE) { + if (Arsse::$user->rightsGet(Arsse::$user->id)==User::RIGHTS_NONE) { return new Response(403); } Service::cleanupPre(); @@ -665,7 +669,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { protected function cleanupAfter(array $url, array $data): Response { // function requires admin rights per spec - if(Arsse::$user->rightsGet(Arsse::$user->id)==User::RIGHTS_NONE) { + if (Arsse::$user->rightsGet(Arsse::$user->id)==User::RIGHTS_NONE) { return new Response(403); } Service::cleanupPost(); @@ -689,4 +693,4 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { ] ]); } -} \ No newline at end of file +} diff --git a/lib/REST/NextCloudNews/Versions.php b/lib/REST/NextCloudNews/Versions.php index 2323f5d..df260cc 100644 --- a/lib/REST/NextCloudNews/Versions.php +++ b/lib/REST/NextCloudNews/Versions.php @@ -1,18 +1,19 @@ method != "GET") { + if ($req->method != "GET") { return new Response(405); } - if(preg_match("<^/?$>",$req->path)) { + if (preg_match("<^/?$>", $req->path)) { // if the request path is an empty string or just a slash, return the supported versions $out = [ 'apiLevels' => [ @@ -25,4 +26,4 @@ class Versions implements \JKingWeb\Arsse\REST\Handler { return new Response(501); } } -} \ No newline at end of file +} diff --git a/lib/REST/Request.php b/lib/REST/Request.php index 2904e0f..b767b56 100644 --- a/lib/REST/Request.php +++ b/lib/REST/Request.php @@ -11,18 +11,18 @@ class Request { public $type =""; public $body = ""; - function __construct(string $method = null, string $url = null, string $body = null, string $contentType = null) { - if(is_null($method)) { + public function __construct(string $method = null, string $url = null, string $body = null, string $contentType = null) { + if (is_null($method)) { $method = $_SERVER['REQUEST_METHOD']; } - if(is_null($url)) { + if (is_null($url)) { $url = $_SERVER['REQUEST_URI']; - } - if(is_null($body)) { + } + if (is_null($body)) { $body = file_get_contents("php://input"); } - if(is_null($contentType)) { - if(isset($_SERVER['HTTP_CONTENT_TYPE'])) { + if (is_null($contentType)) { + if (isset($_SERVER['HTTP_CONTENT_TYPE'])) { $contentType = $_SERVER['HTTP_CONTENT_TYPE']; } else { $contentType = ""; @@ -47,17 +47,17 @@ class Request { $parts = explode("?", $url); $out = ['path' => $parts[0], 'paths' => [''], 'query' => []]; // if there is a query string, parse it - if(isset($parts[1])) { + if (isset($parts[1])) { // split along & to get key-value pairs $query = explode("&", $parts[1]); - for($a = 0; $a < sizeof($query); $a++) { + for ($a = 0; $a < sizeof($query); $a++) { // split each pair, into no more than two parts $data = explode("=", $query[$a], 2); // decode the key $key = rawurldecode($data[0]); // decode the value if there is one $value = ""; - if(isset($data[1])) { + if (isset($data[1])) { $value = rawurldecode($data[1]); } // add the pair to the query output, overwriting earlier values for the same key, is present @@ -66,19 +66,21 @@ class Request { } // also include the path as a set of decoded elements // if the path is an empty string or just / nothing needs be done - if(!in_array($out['path'],["/",""])) { + if (!in_array($out['path'], ["/",""])) { $paths = explode("/", $out['path']); // remove the first and last empty elements, if present (they are artefacts of the splitting; others should remain) - if(!strlen($paths[0])) { + if (!strlen($paths[0])) { array_shift($paths); } - if(!strlen($paths[sizeof($paths)-1])) { + if (!strlen($paths[sizeof($paths)-1])) { array_pop($paths); } // %-decode each path element - $paths = array_map(function($v){return rawurldecode($v);}, $paths); + $paths = array_map(function ($v) { + return rawurldecode($v); + }, $paths); $out['paths'] = $paths; } return $out; } -} \ No newline at end of file +} diff --git a/lib/REST/Response.php b/lib/REST/Response.php index 688c567..fc18723 100644 --- a/lib/REST/Response.php +++ b/lib/REST/Response.php @@ -1,6 +1,7 @@ code = $code; $this->payload = $payload; $this->type = $type; $this->fields = $extraFields; } - function output() { - if(!headers_sent()) { + public function output() { + if (!headers_sent()) { try { $statusText = Arsse::$lang->msg("HTTP.Status.".$this->code); - } catch(\JKingWeb\Arsse\Lang\Exception $e) { + } catch (\JKingWeb\Arsse\Lang\Exception $e) { $statusText = ""; } header("Status: ".$this->code." ".$statusText); $body = ""; - if(!is_null($this->payload)) { + if (!is_null($this->payload)) { header("Content-Type: ".$this->type); - switch($this->type) { - case self::T_JSON: - $body = (string) json_encode($this->payload,\JSON_PRETTY_PRINT); + switch ($this->type) { + case self::T_JSON: + $body = (string) json_encode($this->payload, \JSON_PRETTY_PRINT); break; default: $body = (string) $this->payload; break; } } - foreach($this->fields as $field) { + foreach ($this->fields as $field) { header($field); } echo $body; @@ -49,4 +50,4 @@ class Response { throw new REST\Exception("headersSent"); } } -} \ No newline at end of file +} diff --git a/lib/Service.php b/lib/Service.php index 83f7f3c..baffb32 100644 --- a/lib/Service.php +++ b/lib/Service.php @@ -1,6 +1,7 @@ serviceFrequency); - } catch(\Exception $e) { + } catch (\Exception $e) { return new \DateInterval("PT2M"); } } - function __construct() { + public function __construct() { $driver = Arsse::$conf->serviceDriver; $this->drv = new $driver(); $this->interval = static::interval(); } - function watch(bool $loop = true): \DateTimeInterface { + public function watch(bool $loop = true): \DateTimeInterface { $t = new \DateTime(); do { $this->checkIn(); static::cleanupPre(); $list = Arsse::$db->feedListStale(); - if($list) { + if ($list) { $this->drv->queue(...$list); $this->drv->exec(); $this->drv->clean(); @@ -50,23 +51,23 @@ class Service { } static::cleanupPost(); $t->add($this->interval); - if($loop) { + if ($loop) { do { @time_sleep_until($t->getTimestamp()); - } while($t->getTimestamp() > time()); + } while ($t->getTimestamp() > time()); } - } while($loop); + } while ($loop); return $t; } - function checkIn(): bool { + public function checkIn(): bool { return Arsse::$db->metaSet("service_last_checkin", time(), "datetime"); } - static function hasCheckedIn(): bool { + public static function hasCheckedIn(): bool { $checkin = Arsse::$db->metaGet("service_last_checkin"); // if the service has never checked in, return false - if(!$checkin) { + if (!$checkin) { return false; } // convert the check-in timestamp to a DateTime instance @@ -81,13 +82,13 @@ class Service { return ($checkin >= $limit); } - static function cleanupPre(): bool { + public static function cleanupPre(): bool { // mark unsubscribed feeds as orphaned and delete orphaned feeds that are beyond their retention period return Arsse::$db->feedCleanup(); } - static function cleanupPost(): bool { + public static function cleanupPost(): bool { // delete old articles, according to configured threasholds return Arsse::$db->articleCleanup(); } -} \ No newline at end of file +} diff --git a/lib/Service/Curl/Driver.php b/lib/Service/Curl/Driver.php index b41c9be..1ea52bc 100644 --- a/lib/Service/Curl/Driver.php +++ b/lib/Service/Curl/Driver.php @@ -1,6 +1,7 @@ msg("Driver.Service.Curl.Name"); } - static function requirementsMet(): bool { + public static function requirementsMet(): bool { return extension_loaded("curl"); } - function __construct() { + public function __construct() { //default curl options for individual requests $this->options = [ \CURLOPT_URL => Arsse::$serviceCurlBase."index.php/apps/news/api/v1-2/feeds/update", @@ -42,8 +43,8 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { curl_multi_setopt($this->queue, \CURLMOPT_PIPELINING, 1); } - function queue(int ...$feeds): int { - foreach($feeds as $id) { + public function queue(int ...$feeds): int { + foreach ($feeds as $id) { $h = curl_init(); curl_setopt($h, \CURLOPT_POSTFIELDS, json_encode(['userId' => "", 'feedId' => $id])); $this->handles[] = $h; @@ -52,7 +53,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { return sizeof($this->handles); } - function exec(): int { + public function exec(): int { $active = 0; do { curl_multi_exec($this->queue, $active); @@ -61,12 +62,12 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { return Arsse::$conf->serviceQueueWidth - $active; } - function clean(): bool { - foreach($this->handles as $h) { + public function clean(): bool { + foreach ($this->handles as $h) { curl_multi_remove_handle($this->queue, $h); curl_close($h); } $this->handles = []; return true; } -} \ No newline at end of file +} diff --git a/lib/Service/Driver.php b/lib/Service/Driver.php index fe8f010..50ad0a7 100644 --- a/lib/Service/Driver.php +++ b/lib/Service/Driver.php @@ -3,9 +3,9 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Service; interface Driver { - static function driverName(): string; - static function requirementsMet(): bool; - function queue(int ...$feeds): int; - function exec(): int; - function clean(): bool; -} \ No newline at end of file + public static function driverName(): string; + public static function requirementsMet(): bool; + public function queue(int ...$feeds): int; + public function exec(): int; + public function clean(): bool; +} diff --git a/lib/Service/Forking/Driver.php b/lib/Service/Forking/Driver.php index 4dba4b9..7f4b7b5 100644 --- a/lib/Service/Forking/Driver.php +++ b/lib/Service/Forking/Driver.php @@ -1,36 +1,37 @@ msg("Driver.Service.Forking.Name"); } - static function requirementsMet(): bool { + public static function requirementsMet(): bool { return function_exists("popen"); } - function __construct() { + public function __construct() { } - function queue(int ...$feeds): int { + public function queue(int ...$feeds): int { $this->queue = array_merge($this->queue, $feeds); return sizeof($this->queue); } - function exec(): int { + public function exec(): int { $pp = []; - while($this->queue) { + while ($this->queue) { $id = (int) array_shift($this->queue); $php = '"'.\PHP_BINARY.'"'; $arsse = '"'.$_SERVER['argv'][0].'"'; array_push($pp, popen("$php $arsse feed refresh $id", "r")); } - while($pp) { + while ($pp) { $p = array_pop($pp); fgets($p); // TODO: log output pclose($p); @@ -38,8 +39,8 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { return Arsse::$conf->serviceQueueWidth - sizeof($this->queue); } - function clean(): bool { + public function clean(): bool { $this->queue = []; return true; } -} \ No newline at end of file +} diff --git a/lib/Service/Internal/Driver.php b/lib/Service/Internal/Driver.php index 87afce8..d81f951 100644 --- a/lib/Service/Internal/Driver.php +++ b/lib/Service/Internal/Driver.php @@ -1,38 +1,39 @@ msg("Driver.Service.Internal.Name"); } - static function requirementsMet(): bool { + public static function requirementsMet(): bool { // this driver has no requirements return true; } - function __construct() { + public function __construct() { } - function queue(int ...$feeds): int { + public function queue(int ...$feeds): int { $this->queue = array_merge($this->queue, $feeds); return sizeof($this->queue); } - function exec(): int { - while(sizeof($this->queue)) { + public function exec(): int { + while (sizeof($this->queue)) { $id = array_shift($this->queue); Arsse::$db->feedUpdate($id); } return Arsse::$conf->serviceQueueWidth - sizeof($this->queue); } - function clean(): bool { + public function clean(): bool { $this->queue = []; return true; } -} \ No newline at end of file +} diff --git a/lib/User.php b/lib/User.php index 4012883..b996107 100644 --- a/lib/User.php +++ b/lib/User.php @@ -9,7 +9,7 @@ class User { const RIGHTS_GLOBAL_MANAGER = 75; // able to act for any normal users on any domain; cannot elevate other users const RIGHTS_GLOBAL_ADMIN = 100; // is completely unrestricted - public $id = null; + public $id = null; /** * @var User\Driver @@ -19,11 +19,11 @@ class User { protected $authzSupported = 0; protected $actor = []; - static public function driverList(): array { + public static function driverList(): array { $sep = \DIRECTORY_SEPARATOR; $path = __DIR__.$sep."User".$sep; $classes = []; - foreach(glob($path."*".$sep."Driver.php") as $file) { + foreach (glob($path."*".$sep."Driver.php") as $file) { $name = basename(dirname($file)); $class = NS_BASE."User\\$name\\Driver"; $classes[$class] = $class::driverName(); @@ -37,72 +37,72 @@ class User { } public function __toString() { - if($this->id===null) { + if ($this->id===null) { $this->credentials(); } return (string) $this->id; } // checks whether the logged in user is authorized to act for the affected user (used especially when granting rights) - function authorize(string $affectedUser, string $action, int $newRightsLevel = 0): bool { + public function authorize(string $affectedUser, string $action, int $newRightsLevel = 0): bool { // if authorization checks are disabled (either because we're running the installer or the background updater) just return true - if(!$this->authorizationEnabled()) { + if (!$this->authorizationEnabled()) { return true; } // if we don't have a logged-in user, fetch credentials - if($this->id===null) { + if ($this->id===null) { $this->credentials(); } // if the affected user is the actor and the actor is not trying to grant themselves rights, accept the request - if($affectedUser==Arsse::$user->id && $action != "userRightsSet") { + if ($affectedUser==Arsse::$user->id && $action != "userRightsSet") { return true; } // if we're authorizing something other than a user function and the affected user is not the actor, make sure the affected user exists $this->authorizationEnabled(false); - if(Arsse::$user->id != $affectedUser && strpos($action, "user")!==0 && !$this->exists($affectedUser)) { + if (Arsse::$user->id != $affectedUser && strpos($action, "user")!==0 && !$this->exists($affectedUser)) { throw new User\Exception("doesNotExist", ["action" => $action, "user" => $affectedUser]); } $this->authorizationEnabled(true); // get properties of actor if not already available - if(!sizeof($this->actor)) { + if (!sizeof($this->actor)) { $this->actor = $this->propertiesGet(Arsse::$user->id); } $rights = $this->actor["rights"]; // if actor is a global admin, accept the request - if($rights==User\Driver::RIGHTS_GLOBAL_ADMIN) { + if ($rights==User\Driver::RIGHTS_GLOBAL_ADMIN) { return true; } // if actor is a common user, deny the request - if($rights==User\Driver::RIGHTS_NONE) { + if ($rights==User\Driver::RIGHTS_NONE) { return false; } // if actor is not some other sort of admin, deny the request - if(!in_array($rights,[User\Driver::RIGHTS_GLOBAL_MANAGER,User\Driver::RIGHTS_DOMAIN_MANAGER,User\Driver::RIGHTS_DOMAIN_ADMIN],true)) { + if (!in_array($rights, [User\Driver::RIGHTS_GLOBAL_MANAGER,User\Driver::RIGHTS_DOMAIN_MANAGER,User\Driver::RIGHTS_DOMAIN_ADMIN], true)) { return false; } // if actor is a domain admin/manager and domains don't match, deny the request - if($this->actor["domain"] && $rights != User\Driver::RIGHTS_GLOBAL_MANAGER) { + if ($this->actor["domain"] && $rights != User\Driver::RIGHTS_GLOBAL_MANAGER) { $test = "@".$this->actor["domain"]; - if(substr($affectedUser,-1*strlen($test)) != $test) { + if (substr($affectedUser, -1*strlen($test)) != $test) { return false; } } // certain actions shouldn't check affected user's rights - if(in_array($action, ["userRightsGet","userExists","userList"], true)) { + if (in_array($action, ["userRightsGet","userExists","userList"], true)) { return true; } - if($action=="userRightsSet") { + if ($action=="userRightsSet") { // setting rights above your own is not allowed - if($newRightsLevel > $rights) { + if ($newRightsLevel > $rights) { return false; } // setting yourself to rights you already have is harmless and can be allowed - if($this->id==$affectedUser && $newRightsLevel==$rights) { + if ($this->id==$affectedUser && $newRightsLevel==$rights) { return true; } // managers can only set their own rights, and only to normal user - if(in_array($rights, [User\Driver::RIGHTS_DOMAIN_MANAGER, User\Driver::RIGHTS_GLOBAL_MANAGER])) { - if($this->id != $affectedUser || $newRightsLevel != User\Driver::RIGHTS_NONE) { + if (in_array($rights, [User\Driver::RIGHTS_DOMAIN_MANAGER, User\Driver::RIGHTS_GLOBAL_MANAGER])) { + if ($this->id != $affectedUser || $newRightsLevel != User\Driver::RIGHTS_NONE) { return false; } return true; @@ -110,20 +110,20 @@ class User { } $affectedRights = $this->rightsGet($affectedUser); // managers can only act on themselves (checked above) or regular users - if(in_array($rights,[User\Driver::RIGHTS_GLOBAL_MANAGER,User\Driver::RIGHTS_DOMAIN_MANAGER]) && $affectedRights != User\Driver::RIGHTS_NONE) { + if (in_array($rights, [User\Driver::RIGHTS_GLOBAL_MANAGER,User\Driver::RIGHTS_DOMAIN_MANAGER]) && $affectedRights != User\Driver::RIGHTS_NONE) { return false; } // domain admins canot act above themselves - if(!in_array($affectedRights,[User\Driver::RIGHTS_NONE,User\Driver::RIGHTS_DOMAIN_MANAGER,User\Driver::RIGHTS_DOMAIN_ADMIN])) { + if (!in_array($affectedRights, [User\Driver::RIGHTS_NONE,User\Driver::RIGHTS_DOMAIN_MANAGER,User\Driver::RIGHTS_DOMAIN_ADMIN])) { return false; } return true; } public function credentials(): array { - if($_SERVER['PHP_AUTH_USER']) { + if ($_SERVER['PHP_AUTH_USER']) { $out = ["user" => $_SERVER['PHP_AUTH_USER'], "password" => $_SERVER['PHP_AUTH_PW']]; - } else if($_SERVER['REMOTE_USER']) { + } elseif ($_SERVER['REMOTE_USER']) { $out = ["user" => $_SERVER['REMOTE_USER'], "password" => ""]; } else { $out = ["user" => "", "password" => ""]; @@ -133,25 +133,25 @@ class User { } public function auth(string $user = null, string $password = null): bool { - if($user===null) { + if ($user===null) { return $this->authHTTP(); } else { $this->id = $user; $this->actor = []; - switch($this->u->driverFunctions("auth")) { + switch ($this->u->driverFunctions("auth")) { case User\Driver::FUNC_EXTERNAL: - if(Arsse::$conf->userPreAuth) { + if (Arsse::$conf->userPreAuth) { $out = true; } else { $out = $this->u->auth($user, $password); } - if($out && !Arsse::$db->userExists($user)) { + if ($out && !Arsse::$db->userExists($user)) { $this->autoProvision($user, $password); } return $out; case User\Driver::FUNC_INTERNAL: - if(Arsse::$conf->userPreAuth) { - if(!Arsse::$db->userExists($user)) { + if (Arsse::$conf->userPreAuth) { + if (!Arsse::$db->userExists($user)) { $this->autoProvision($user, $password); } return true; @@ -166,7 +166,7 @@ class User { public function authHTTP(): bool { $cred = $this->credentials(); - if(!$cred["user"]) { + if (!$cred["user"]) { return false; } return $this->auth($cred["user"], $cred["password"]); @@ -178,15 +178,15 @@ class User { public function list(string $domain = null): array { $func = "userList"; - switch($this->u->driverFunctions($func)) { + switch ($this->u->driverFunctions($func)) { case User\Driver::FUNC_EXTERNAL: // we handle authorization checks for external drivers - if($domain===null) { - if(!$this->authorize("@".$domain, $func)) { + if ($domain===null) { + if (!$this->authorize("@".$domain, $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $domain]); } } else { - if(!$this->authorize("", $func)) { + if (!$this->authorize("", $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => "all users"]); } } @@ -199,11 +199,11 @@ class User { } public function authorizationEnabled(bool $setting = null): bool { - if(is_null($setting)) { + if (is_null($setting)) { return !$this->authz; } $this->authz += ($setting ? -1 : 1); - if($this->authz < 0) { + if ($this->authz < 0) { $this->authz = 0; } return !$this->authz; @@ -211,14 +211,14 @@ class User { public function exists(string $user): bool { $func = "userExists"; - switch($this->u->driverFunctions($func)) { + switch ($this->u->driverFunctions($func)) { case User\Driver::FUNC_EXTERNAL: // we handle authorization checks for external drivers - if(!$this->authorize($user, $func)) { + if (!$this->authorize($user, $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]); } $out = $this->u->userExists($user); - if($out && !Arsse::$db->userExists($user)) { + if ($out && !Arsse::$db->userExists($user)) { $this->autoProvision($user, ""); } return $out; @@ -233,15 +233,15 @@ class User { public function add($user, $password = null): string { $func = "userAdd"; - switch($this->u->driverFunctions($func)) { + switch ($this->u->driverFunctions($func)) { case User\Driver::FUNC_EXTERNAL: // we handle authorization checks for external drivers - if(!$this->authorize($user, $func)) { + if (!$this->authorize($user, $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]); } $newPassword = $this->u->userAdd($user, $password); // if there was no exception and we don't have the user in the internal database, add it - if(!Arsse::$db->userExists($user)) { + if (!Arsse::$db->userExists($user)) { $this->autoProvision($user, $newPassword); } return $newPassword; @@ -255,16 +255,16 @@ class User { public function remove(string $user): bool { $func = "userRemove"; - switch($this->u->driverFunctions($func)) { + switch ($this->u->driverFunctions($func)) { case User\Driver::FUNC_EXTERNAL: // we handle authorization checks for external drivers - if(!$this->authorize($user, $func)) { + if (!$this->authorize($user, $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]); } $out = $this->u->userRemove($user); - if($out && Arsse::$db->userExists($user)) { + if ($out && Arsse::$db->userExists($user)) { // if the user was removed and we have it in our data, remove it there - if(!Arsse::$db->userExists($user)) { + if (!Arsse::$db->userExists($user)) { Arsse::$db->userRemove($user); } } @@ -279,14 +279,14 @@ class User { public function passwordSet(string $user, string $newPassword = null, $oldPassword = null): string { $func = "userPasswordSet"; - switch($this->u->driverFunctions($func)) { + switch ($this->u->driverFunctions($func)) { case User\Driver::FUNC_EXTERNAL: // we handle authorization checks for external drivers - if(!$this->authorize($user, $func)) { + if (!$this->authorize($user, $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]); } $out = $this->u->userPasswordSet($user, $newPassword, $oldPassword); - if(Arsse::$db->userExists($user)) { + if (Arsse::$db->userExists($user)) { // if the password change was successful and the user exists, set the internal password to the same value Arsse::$db->userPasswordSet($user, $out); } else { @@ -305,8 +305,8 @@ class User { public function propertiesGet(string $user, bool $withAvatar = false): array { // prepare default values $domain = null; - if(strrpos($user,"@")!==false) { - $domain = substr($user,strrpos($user,"@")+1); + if (strrpos($user, "@")!==false) { + $domain = substr($user, strrpos($user, "@")+1); } $init = [ "id" => $user, @@ -315,19 +315,19 @@ class User { "domain" => $domain ]; $func = "userPropertiesGet"; - switch($this->u->driverFunctions($func)) { + switch ($this->u->driverFunctions($func)) { case User\Driver::FUNC_EXTERNAL: // we handle authorization checks for external drivers - if(!$this->authorize($user, $func)) { + if (!$this->authorize($user, $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]); } $out = array_merge($init, $this->u->userPropertiesGet($user)); // remove password if it is return (not exhaustive, but...) - if(array_key_exists('password', $out)) { + if (array_key_exists('password', $out)) { unset($out['password']); } // if the user does not exist in the internal database, add it - if(!Arsse::$db->userExists($user)) { + if (!Arsse::$db->userExists($user)) { $this->autoProvision($user, "", $out); } return $out; @@ -342,20 +342,20 @@ class User { public function propertiesSet(string $user, array $properties): array { // remove from the array any values which should be set specially - foreach(['id', 'domain', 'password', 'rights'] as $key) { - if(array_key_exists($key, $properties)) { + foreach (['id', 'domain', 'password', 'rights'] as $key) { + if (array_key_exists($key, $properties)) { unset($properties[$key]); } } $func = "userPropertiesSet"; - switch($this->u->driverFunctions($func)) { + switch ($this->u->driverFunctions($func)) { case User\Driver::FUNC_EXTERNAL: // we handle authorization checks for external drivers - if(!$this->authorize($user, $func)) { + if (!$this->authorize($user, $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]); } $out = $this->u->userPropertiesSet($user, $properties); - if(Arsse::$db->userExists($user)) { + if (Arsse::$db->userExists($user)) { // if the property change was successful and the user exists, set the internal properties to the same values Arsse::$db->userPropertiesSet($user, $out); } else { @@ -373,15 +373,15 @@ class User { public function rightsGet(string $user): int { $func = "userRightsGet"; - switch($this->u->driverFunctions($func)) { + switch ($this->u->driverFunctions($func)) { case User\Driver::FUNC_EXTERNAL: // we handle authorization checks for external drivers - if(!$this->authorize($user, $func)) { + if (!$this->authorize($user, $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]); } $out = $this->u->userRightsGet($user); // if the user does not exist in the internal database, add it - if(!Arsse::$db->userExists($user)) { + if (!Arsse::$db->userExists($user)) { $this->autoProvision($user, "", null, $out); } return $out; @@ -396,20 +396,20 @@ class User { public function rightsSet(string $user, int $level): bool { $func = "userRightsSet"; - switch($this->u->driverFunctions($func)) { + switch ($this->u->driverFunctions($func)) { case User\Driver::FUNC_EXTERNAL: // we handle authorization checks for external drivers - if(!$this->authorize($user, $func)) { + if (!$this->authorize($user, $func)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]); } $out = $this->u->userRightsSet($user, $level); // if the user does not exist in the internal database, add it - if($out && Arsse::$db->userExists($user)) { + if ($out && Arsse::$db->userExists($user)) { $authz = $this->authorizationEnabled(); $this->authorizationEnabled(false); Arsse::$db->userRightsSet($user, $level); $this->authorizationEnabled($authz); - } else if($out) { + } elseif ($out) { $this->autoProvision($user, "", null, $level); } return $out; @@ -429,13 +429,14 @@ class User { // set the user rights Arsse::$db->userRightsSet($user, $rights); // set the user properties... - if($properties===null) { + if ($properties===null) { // if nothing is provided but the driver uses an external function, try to get the current values from the external source try { - if($this->u->driverFunctions("userPropertiesGet")==User\Driver::FUNC_EXTERNAL) { + if ($this->u->driverFunctions("userPropertiesGet")==User\Driver::FUNC_EXTERNAL) { Arsse::$db->userPropertiesSet($user, $this->u->userPropertiesGet($user)); } - } catch(\Throwable $e) {} + } catch (\Throwable $e) { + } } else { // otherwise if values are provided, use those Arsse::$db->userPropertiesSet($user, $properties); @@ -444,4 +445,4 @@ class User { $this->authorizationEnabled(true); return $out; } -} \ No newline at end of file +} diff --git a/lib/User/Driver.php b/lib/User/Driver.php index b842827..52a93d1 100644 --- a/lib/User/Driver.php +++ b/lib/User/Driver.php @@ -2,7 +2,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse\User; -Interface Driver { +interface Driver { const FUNC_NOT_IMPLEMENTED = 0; const FUNC_INTERNAL = 1; const FUNC_EXTERNAL = 2; @@ -14,29 +14,29 @@ Interface Driver { const RIGHTS_GLOBAL_ADMIN = 100; // is completely unrestricted // returns an instance of a class implementing this interface. - function __construct(); + public function __construct(); // returns a human-friendly name for the driver (for display in installer, for example) - static function driverName(): string; + public static function driverName(): string; // returns an array (or single queried member of same) of methods defined by this interface and whether the class implements the internal function or a custom version - function driverFunctions(string $function = null); + public function driverFunctions(string $function = null); // authenticates a user against their name and password - function auth(string $user, string $password): bool; + public function auth(string $user, string $password): bool; // checks whether a user exists - function userExists(string $user): bool; + public function userExists(string $user): bool; // adds a user - function userAdd(string $user, string $password = null): string; + public function userAdd(string $user, string $password = null): string; // removes a user - function userRemove(string $user): bool; + public function userRemove(string $user): bool; // lists all users - function userList(string $domain = null): array; + public function userList(string $domain = null): array; // sets a user's password; if the driver does not require the old password, it may be ignored - function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string; + public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string; // gets user metadata (currently not useful) - function userPropertiesGet(string $user): array; + public function userPropertiesGet(string $user): array; // sets user metadata (currently not useful) - function userPropertiesSet(string $user, array $properties): array; + public function userPropertiesSet(string $user, array $properties): array; // returns a user's access level according to RIGHTS_* constants (or some custom semantics, if using custom implementation of authorize()) - function userRightsGet(string $user): int; + public function userRightsGet(string $user): int; // sets a user's access level - function userRightsSet(string $user, int $level): bool; -} \ No newline at end of file + public function userRightsSet(string $user, int $level): bool; +} diff --git a/lib/User/Exception.php b/lib/User/Exception.php index c9e134c..dbe60ce 100644 --- a/lib/User/Exception.php +++ b/lib/User/Exception.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\User; class Exception extends \JKingWeb\Arsse\AbstractException { -} \ No newline at end of file +} diff --git a/lib/User/ExceptionAuthz.php b/lib/User/ExceptionAuthz.php index 87b13bd..4346251 100644 --- a/lib/User/ExceptionAuthz.php +++ b/lib/User/ExceptionAuthz.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\User; class ExceptionAuthz extends Exception { -} \ No newline at end of file +} diff --git a/lib/User/ExceptionNotImplemented.php b/lib/User/ExceptionNotImplemented.php index f23b2f4..278a9d4 100644 --- a/lib/User/ExceptionNotImplemented.php +++ b/lib/User/ExceptionNotImplemented.php @@ -3,4 +3,4 @@ declare(strict_types=1); namespace JKingWeb\Arsse\User; class ExceptionNotImplemented extends Exception { -} \ No newline at end of file +} diff --git a/lib/User/Internal/Driver.php b/lib/User/Internal/Driver.php index bdd5c36..ebdcc20 100644 --- a/lib/User/Internal/Driver.php +++ b/lib/User/Internal/Driver.php @@ -19,15 +19,15 @@ final class Driver implements \JKingWeb\Arsse\User\Driver { "userRightsSet" => self::FUNC_INTERNAL, ]; - static public function driverName(): string { + public static function driverName(): string { return Arsse::$lang->msg("Driver.User.Internal.Name"); } public function driverFunctions(string $function = null) { - if($function===null) { + if ($function===null) { return $this->functions; } - if(array_key_exists($function, $this->functions)) { + if (array_key_exists($function, $this->functions)) { return $this->functions[$function]; } else { return self::FUNC_NOT_IMPLEMENTED; @@ -35,4 +35,4 @@ final class Driver implements \JKingWeb\Arsse\User\Driver { } // see InternalFunctions.php for bulk of methods -} \ No newline at end of file +} diff --git a/lib/User/Internal/InternalFunctions.php b/lib/User/Internal/InternalFunctions.php index 9e8862e..ed78956 100644 --- a/lib/User/Internal/InternalFunctions.php +++ b/lib/User/Internal/InternalFunctions.php @@ -1,6 +1,7 @@ userPasswordGet($user); - } catch(Exception $e) { + } catch (Exception $e) { return false; } - if($password==="" && $hash==="") { + if ($password==="" && $hash==="") { return true; } return password_verify($password, $hash); } - function userExists(string $user): bool { + public function userExists(string $user): bool { return Arsse::$db->userExists($user); } - function userAdd(string $user, string $password = null): string { + public function userAdd(string $user, string $password = null): string { return Arsse::$db->userAdd($user, $password); } - function userRemove(string $user): bool { + public function userRemove(string $user): bool { return Arsse::$db->userRemove($user); } - function userList(string $domain = null): array { + public function userList(string $domain = null): array { return Arsse::$db->userList($domain); } - function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string { + public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string { return Arsse::$db->userPasswordSet($user, $newPassword); } - function userPropertiesGet(string $user): array { + public function userPropertiesGet(string $user): array { return Arsse::$db->userPropertiesGet($user); } - function userPropertiesSet(string $user, array $properties): array { + public function userPropertiesSet(string $user, array $properties): array { return Arsse::$db->userPropertiesSet($user, $properties); } - function userRightsGet(string $user): int { + public function userRightsGet(string $user): int { return Arsse::$db->userRightsGet($user); } - function userRightsSet(string $user, int $level): bool { + public function userRightsSet(string $user, int $level): bool { return Arsse::$db->userRightsSet($user, $level); } -} \ No newline at end of file +} diff --git a/tests/Conf/TestConf.php b/tests/Conf/TestConf.php index 5f99d02..6839b2f 100644 --- a/tests/Conf/TestConf.php +++ b/tests/Conf/TestConf.php @@ -1,14 +1,15 @@ clearData(); self::$vfs = vfsStream::setup("root", null, [ 'confGood' => ' "xx");', @@ -26,18 +27,18 @@ class TestConf extends Test\AbstractTest { chmod(self::$path."confForbidden", 0000); } - function tearDown() { + public function tearDown() { self::$path = null; self::$vfs = null; $this->clearData(); } - function testLoadDefaultValues() { + public function testLoadDefaultValues() { $this->assertInstanceOf(Conf::class, new Conf()); } /** @depends testLoadDefaultValues */ - function testImportFromArray() { + public function testImportFromArray() { $arr = ['lang' => "xx"]; $conf = new Conf(); $conf->import($arr); @@ -45,7 +46,7 @@ class TestConf extends Test\AbstractTest { } /** @depends testImportFromArray */ - function testImportFromFile() { + public function testImportFromFile() { $conf = new Conf(); $conf->importFile(self::$path."confGood"); $this->assertEquals("xx", $conf->lang); @@ -54,43 +55,43 @@ class TestConf extends Test\AbstractTest { } /** @depends testImportFromFile */ - function testImportFromMissingFile() { + public function testImportFromMissingFile() { $this->assertException("fileMissing", "Conf"); $conf = new Conf(self::$path."confMissing"); } /** @depends testImportFromFile */ - function testImportFromEmptyFile() { + public function testImportFromEmptyFile() { $this->assertException("fileCorrupt", "Conf"); $conf = new Conf(self::$path."confEmpty"); } /** @depends testImportFromFile */ - function testImportFromFileWithoutReadPermission() { + public function testImportFromFileWithoutReadPermission() { $this->assertException("fileUnreadable", "Conf"); $conf = new Conf(self::$path."confUnreadable"); } /** @depends testImportFromFile */ - function testImportFromFileWhichIsNotAnArray() { + public function testImportFromFileWhichIsNotAnArray() { $this->assertException("fileCorrupt", "Conf"); $conf = new Conf(self::$path."confNotArray"); } /** @depends testImportFromFile */ - function testImportFromFileWhichIsNotPhp() { + public function testImportFromFileWhichIsNotPhp() { $this->assertException("fileCorrupt", "Conf"); // this should not print the output of the non-PHP file $conf = new Conf(self::$path."confNotPHP"); } /** @depends testImportFromFile */ - function testImportFromCorruptFile() { + public function testImportFromCorruptFile() { $this->assertException("fileCorrupt", "Conf"); $conf = new Conf(self::$path."confCorrupt"); } - function testExportToArray() { + public function testExportToArray() { $conf = new Conf(); $conf->lang = ["en", "fr"]; // should not be exported: not scalar $conf->dbSQLite3File = "test.db"; // should be exported: value changed @@ -105,9 +106,9 @@ class TestConf extends Test\AbstractTest { $this->assertArraySubset($exp, $res); } - /** @depends testExportToArray + /** @depends testExportToArray * @depends testImportFromFile */ - function testExportToFile() { + public function testExportToFile() { $conf = new Conf(); $conf->lang = ["en", "fr"]; // should not be exported: not scalar $conf->dbSQLite3File = "test.db"; // should be exported: value changed @@ -125,12 +126,12 @@ class TestConf extends Test\AbstractTest { $this->assertArraySubset($exp, $arr); } - function testExportToFileWithoutWritePermission() { + public function testExportToFileWithoutWritePermission() { $this->assertException("fileUnwritable", "Conf"); (new Conf)->exportFile(self::$path."confUnreadable"); } - function testExportToFileWithoutCreatePermission() { + public function testExportToFileWithoutCreatePermission() { $this->assertException("fileUncreatable", "Conf"); (new Conf)->exportFile(self::$path."confForbidden/conf"); } diff --git a/tests/Db/SQLite3/Database/TestDatabaseArticleSQLite3.php b/tests/Db/SQLite3/Database/TestDatabaseArticleSQLite3.php index ebd46f2..6049e7b 100644 --- a/tests/Db/SQLite3/Database/TestDatabaseArticleSQLite3.php +++ b/tests/Db/SQLite3/Database/TestDatabaseArticleSQLite3.php @@ -7,4 +7,4 @@ class TestDatabaseArticleSQLite3 extends Test\AbstractTest { use Test\Database\Setup; use Test\Database\DriverSQLite3; use Test\Database\SeriesArticle; -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/Database/TestDatabaseCleanupSQLite3.php b/tests/Db/SQLite3/Database/TestDatabaseCleanupSQLite3.php index b548c48..101e4ed 100644 --- a/tests/Db/SQLite3/Database/TestDatabaseCleanupSQLite3.php +++ b/tests/Db/SQLite3/Database/TestDatabaseCleanupSQLite3.php @@ -7,4 +7,4 @@ class TestDatabaseCleanupSQLite3 extends Test\AbstractTest { use Test\Database\Setup; use Test\Database\DriverSQLite3; use Test\Database\SeriesCleanup; -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/Database/TestDatabaseFeedSQLite3.php b/tests/Db/SQLite3/Database/TestDatabaseFeedSQLite3.php index 7db96a3..2808e75 100644 --- a/tests/Db/SQLite3/Database/TestDatabaseFeedSQLite3.php +++ b/tests/Db/SQLite3/Database/TestDatabaseFeedSQLite3.php @@ -7,4 +7,4 @@ class TestDatabaseFeedSQLite3 extends Test\AbstractTest { use Test\Database\Setup; use Test\Database\DriverSQLite3; use Test\Database\SeriesFeed; -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/Database/TestDatabaseFolderSQLite3.php b/tests/Db/SQLite3/Database/TestDatabaseFolderSQLite3.php index 448b046..251927a 100644 --- a/tests/Db/SQLite3/Database/TestDatabaseFolderSQLite3.php +++ b/tests/Db/SQLite3/Database/TestDatabaseFolderSQLite3.php @@ -7,4 +7,4 @@ class TestDatabaseFolderSQLite3 extends Test\AbstractTest { use Test\Database\Setup; use Test\Database\DriverSQLite3; use Test\Database\SeriesFolder; -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/Database/TestDatabaseMetaSQLite3.php b/tests/Db/SQLite3/Database/TestDatabaseMetaSQLite3.php index e9e132b..8a3bbf8 100644 --- a/tests/Db/SQLite3/Database/TestDatabaseMetaSQLite3.php +++ b/tests/Db/SQLite3/Database/TestDatabaseMetaSQLite3.php @@ -7,4 +7,4 @@ class TestDatabaseMetaSQLite3 extends Test\AbstractTest { use Test\Database\Setup; use Test\Database\DriverSQLite3; use Test\Database\SeriesMeta; -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/Database/TestDatabaseMiscellanySQLite3.php b/tests/Db/SQLite3/Database/TestDatabaseMiscellanySQLite3.php index 7075c3e..4fe0c52 100644 --- a/tests/Db/SQLite3/Database/TestDatabaseMiscellanySQLite3.php +++ b/tests/Db/SQLite3/Database/TestDatabaseMiscellanySQLite3.php @@ -7,4 +7,4 @@ class TestDatabaseMiscellanySQLite3 extends Test\AbstractTest { use Test\Database\Setup; use Test\Database\DriverSQLite3; use Test\Database\SeriesMiscellany; -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/Database/TestDatabaseSubscriptionSQLite3.php b/tests/Db/SQLite3/Database/TestDatabaseSubscriptionSQLite3.php index bf30662..7b0d099 100644 --- a/tests/Db/SQLite3/Database/TestDatabaseSubscriptionSQLite3.php +++ b/tests/Db/SQLite3/Database/TestDatabaseSubscriptionSQLite3.php @@ -7,4 +7,4 @@ class TestDatabaseSubscriptionSQLite3 extends Test\AbstractTest { use Test\Database\Setup; use Test\Database\DriverSQLite3; use Test\Database\SeriesSubscription; -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/Database/TestDatabaseUserSQLite3.php b/tests/Db/SQLite3/Database/TestDatabaseUserSQLite3.php index dfba48b..ee3f2be 100644 --- a/tests/Db/SQLite3/Database/TestDatabaseUserSQLite3.php +++ b/tests/Db/SQLite3/Database/TestDatabaseUserSQLite3.php @@ -7,4 +7,4 @@ class TestDatabaseUserSQLite3 extends Test\AbstractTest { use Test\Database\Setup; use Test\Database\DriverSQLite3; use Test\Database\SeriesUser; -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/TestDbDriverCreationSQLite3.php b/tests/Db/SQLite3/TestDbDriverCreationSQLite3.php index 1f345c5..a176ea8 100644 --- a/tests/Db/SQLite3/TestDbDriverCreationSQLite3.php +++ b/tests/Db/SQLite3/TestDbDriverCreationSQLite3.php @@ -1,6 +1,7 @@ markTestSkipped("SQLite extension not loaded"); } $this->clearData(); @@ -88,15 +89,15 @@ class TestDbDriverCreationSQLite3 extends Test\AbstractTest { $this->path = $path = $vfs->url()."/"; // set up access blocks chmod($path."Cmain", 0555); - chmod($path."Cwal", 0555); - chmod($path."Cshm", 0555); - chmod($path."Rmain/arsse.db", 0333); + chmod($path."Cwal", 0555); + chmod($path."Cshm", 0555); + chmod($path."Rmain/arsse.db", 0333); chmod($path."Rwal/arsse.db-wal", 0333); chmod($path."Rshm/arsse.db-shm", 0333); - chmod($path."Wmain/arsse.db", 0555); + chmod($path."Wmain/arsse.db", 0555); chmod($path."Wwal/arsse.db-wal", 0555); chmod($path."Wshm/arsse.db-shm", 0555); - chmod($path."Amain/arsse.db", 0111); + chmod($path."Amain/arsse.db", 0111); chmod($path."Awal/arsse.db-wal", 0111); chmod($path."Ashm/arsse.db-shm", 0111); // set up configuration @@ -105,85 +106,85 @@ class TestDbDriverCreationSQLite3 extends Test\AbstractTest { // set up database shim } - function tearDown() { + public function tearDown() { $this->clearData(); } - function testFailToCreateDatabase() { + public function testFailToCreateDatabase() { Arsse::$conf->dbSQLite3File = $this->path."Cmain/arsse.db"; $this->assertException("fileUncreatable", "Db"); new Db\SQLite3\Driver; } - function testFailToCreateJournal() { + public function testFailToCreateJournal() { Arsse::$conf->dbSQLite3File = $this->path."Cwal/arsse.db"; $this->assertException("fileUncreatable", "Db"); new Db\SQLite3\Driver; } - function testFailToCreateSharedMmeory() { + public function testFailToCreateSharedMmeory() { Arsse::$conf->dbSQLite3File = $this->path."Cshm/arsse.db"; $this->assertException("fileUncreatable", "Db"); new Db\SQLite3\Driver; } - function testFailToReadDatabase() { + public function testFailToReadDatabase() { Arsse::$conf->dbSQLite3File = $this->path."Rmain/arsse.db"; $this->assertException("fileUnreadable", "Db"); new Db\SQLite3\Driver; } - function testFailToReadJournal() { + public function testFailToReadJournal() { Arsse::$conf->dbSQLite3File = $this->path."Rwal/arsse.db"; $this->assertException("fileUnreadable", "Db"); new Db\SQLite3\Driver; } - function testFailToReadSharedMmeory() { + public function testFailToReadSharedMmeory() { Arsse::$conf->dbSQLite3File = $this->path."Rshm/arsse.db"; $this->assertException("fileUnreadable", "Db"); new Db\SQLite3\Driver; } - function testFailToWriteToDatabase() { + public function testFailToWriteToDatabase() { Arsse::$conf->dbSQLite3File = $this->path."Wmain/arsse.db"; $this->assertException("fileUnwritable", "Db"); new Db\SQLite3\Driver; } - function testFailToWriteToJournal() { + public function testFailToWriteToJournal() { Arsse::$conf->dbSQLite3File = $this->path."Wwal/arsse.db"; $this->assertException("fileUnwritable", "Db"); new Db\SQLite3\Driver; } - function testFailToWriteToSharedMmeory() { + public function testFailToWriteToSharedMmeory() { Arsse::$conf->dbSQLite3File = $this->path."Wshm/arsse.db"; $this->assertException("fileUnwritable", "Db"); new Db\SQLite3\Driver; } - function testFailToAccessDatabase() { + public function testFailToAccessDatabase() { Arsse::$conf->dbSQLite3File = $this->path."Amain/arsse.db"; $this->assertException("fileUnusable", "Db"); new Db\SQLite3\Driver; } - function testFailToAccessJournal() { + public function testFailToAccessJournal() { Arsse::$conf->dbSQLite3File = $this->path."Awal/arsse.db"; $this->assertException("fileUnusable", "Db"); new Db\SQLite3\Driver; } - function testFailToAccessSharedMmeory() { + public function testFailToAccessSharedMmeory() { Arsse::$conf->dbSQLite3File = $this->path."Ashm/arsse.db"; $this->assertException("fileUnusable", "Db"); new Db\SQLite3\Driver; } - function testAssumeDatabaseCorruption() { + public function testAssumeDatabaseCorruption() { Arsse::$conf->dbSQLite3File = $this->path."corrupt/arsse.db"; $this->assertException("fileCorrupt", "Db"); new Db\SQLite3\Driver; } -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/TestDbDriverSQLite3.php b/tests/Db/SQLite3/TestDbDriverSQLite3.php index 5a6a23c..4a2058d 100644 --- a/tests/Db/SQLite3/TestDbDriverSQLite3.php +++ b/tests/Db/SQLite3/TestDbDriverSQLite3.php @@ -2,7 +2,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse; -/** +/** * @covers \JKingWeb\Arsse\Db\SQLite3\Driver * @covers \JKingWeb\Arsse\Db\SQLite3\ExceptionBuilder */ class TestDbDriverSQLite3 extends Test\AbstractTest { @@ -10,8 +10,8 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { protected $drv; protected $ch; - function setUp() { - if(!extension_loaded("sqlite3")) { + public function setUp() { + if (!extension_loaded("sqlite3")) { $this->markTestSkipped("SQLite extension not loaded"); } $this->clearData(); @@ -24,110 +24,110 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->ch->enableExceptions(true); } - function tearDown() { + public function tearDown() { unset($this->drv); unset($this->ch); - if(isset(Arsse::$conf)) { + if (isset(Arsse::$conf)) { unlink(Arsse::$conf->dbSQLite3File); } $this->clearData(); } - function testFetchDriverName() { + public function testFetchDriverName() { $class = Arsse::$conf->dbDriver; $this->assertTrue(strlen($class::driverName()) > 0); } - function testExecAValidStatement() { + public function testExecAValidStatement() { $this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key)")); } - function testExecAnInvalidStatement() { + public function testExecAnInvalidStatement() { $this->assertException("engineErrorGeneral", "Db"); $this->drv->exec("And the meek shall inherit the earth..."); } - function testExecMultipleStatements() { + public function testExecMultipleStatements() { $this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key); INSERT INTO test(id) values(2112)")); $this->assertEquals(2112, $this->ch->querySingle("SELECT id from test")); } - function testExecTimeout() { + public function testExecTimeout() { $this->ch->exec("BEGIN EXCLUSIVE TRANSACTION"); $this->assertException("general", "Db", "ExceptionTimeout"); $this->drv->exec("CREATE TABLE test(id integer primary key)"); } - function testExecConstraintViolation() { + public function testExecConstraintViolation() { $this->drv->exec("CREATE TABLE test(id integer not null)"); $this->assertException("constraintViolation", "Db", "ExceptionInput"); $this->drv->exec("INSERT INTO test(id) values(null)"); } - function testExecTypeViolation() { + public function testExecTypeViolation() { $this->drv->exec("CREATE TABLE test(id integer primary key)"); $this->assertException("typeViolation", "Db", "ExceptionInput"); $this->drv->exec("INSERT INTO test(id) values('ook')"); } - function testMakeAValidQuery() { + public function testMakeAValidQuery() { $this->assertInstanceOf(Db\Result::class, $this->drv->query("SELECT 1")); } - function testMakeAnInvalidQuery() { + public function testMakeAnInvalidQuery() { $this->assertException("engineErrorGeneral", "Db"); $this->drv->query("Apollo was astonished; Dionysus thought me mad"); } - function testQueryTimeout() { + public function testQueryTimeout() { $this->ch->exec("BEGIN EXCLUSIVE TRANSACTION"); $this->assertException("general", "Db", "ExceptionTimeout"); $this->drv->query("CREATE TABLE test(id integer primary key)"); } - function testQueryConstraintViolation() { + public function testQueryConstraintViolation() { $this->drv->exec("CREATE TABLE test(id integer not null)"); $this->assertException("constraintViolation", "Db", "ExceptionInput"); $this->drv->query("INSERT INTO test(id) values(null)"); } - function testQueryTypeViolation() { + public function testQueryTypeViolation() { $this->drv->exec("CREATE TABLE test(id integer primary key)"); $this->assertException("typeViolation", "Db", "ExceptionInput"); $this->drv->query("INSERT INTO test(id) values('ook')"); } - function testPrepareAValidQuery() { + public function testPrepareAValidQuery() { $s = $this->drv->prepare("SELECT ?, ?", "int", "int"); $this->assertInstanceOf(Db\Statement::class, $s); } - function testPrepareAnInvalidQuery() { + public function testPrepareAnInvalidQuery() { $this->assertException("engineErrorGeneral", "Db"); $s = $this->drv->prepare("This is an invalid query", "int", "int"); } - function testCreateASavepoint() { + public function testCreateASavepoint() { $this->assertEquals(1, $this->drv->savepointCreate()); $this->assertEquals(2, $this->drv->savepointCreate()); $this->assertEquals(3, $this->drv->savepointCreate()); } - function testReleaseASavepoint() { + public function testReleaseASavepoint() { $this->assertEquals(1, $this->drv->savepointCreate()); $this->assertEquals(true, $this->drv->savepointRelease()); $this->assertException("invalid", "Db", "ExceptionSavepoint"); $this->drv->savepointRelease(); } - function testUndoASavepoint() { + public function testUndoASavepoint() { $this->assertEquals(1, $this->drv->savepointCreate()); $this->assertEquals(true, $this->drv->savepointUndo()); $this->assertException("invalid", "Db", "ExceptionSavepoint"); $this->drv->savepointUndo(); } - function testManipulateSavepoints() { + public function testManipulateSavepoints() { $this->assertEquals(1, $this->drv->savepointCreate()); $this->assertEquals(2, $this->drv->savepointCreate()); $this->assertEquals(3, $this->drv->savepointCreate()); @@ -144,7 +144,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->drv->savepointRelease(2); } - function testManipulateSavepointsSomeMore() { + public function testManipulateSavepointsSomeMore() { $this->assertEquals(1, $this->drv->savepointCreate()); $this->assertEquals(2, $this->drv->savepointCreate()); $this->assertEquals(3, $this->drv->savepointCreate()); @@ -155,7 +155,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->drv->savepointUndo(2); } - function testBeginATransaction() { + public function testBeginATransaction() { $select = "SELECT count(*) FROM test"; $insert = "INSERT INTO test(id) values(null)"; $this->drv->exec("CREATE TABLE test(id integer primary key)"); @@ -168,7 +168,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->assertEquals(0, $this->ch->querySingle($select)); } - function testCommitATransaction() { + public function testCommitATransaction() { $select = "SELECT count(*) FROM test"; $insert = "INSERT INTO test(id) values(null)"; $this->drv->exec("CREATE TABLE test(id integer primary key)"); @@ -181,7 +181,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->assertEquals(1, $this->ch->querySingle($select)); } - function testRollbackATransaction() { + public function testRollbackATransaction() { $select = "SELECT count(*) FROM test"; $insert = "INSERT INTO test(id) values(null)"; $this->drv->exec("CREATE TABLE test(id integer primary key)"); @@ -194,7 +194,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->assertEquals(0, $this->ch->querySingle($select)); } - function testBeginChainedTransactions() { + public function testBeginChainedTransactions() { $select = "SELECT count(*) FROM test"; $insert = "INSERT INTO test(id) values(null)"; $this->drv->exec("CREATE TABLE test(id integer primary key)"); @@ -208,7 +208,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->assertEquals(0, $this->ch->querySingle($select)); } - function testCommitChainedTransactions() { + public function testCommitChainedTransactions() { $select = "SELECT count(*) FROM test"; $insert = "INSERT INTO test(id) values(null)"; $this->drv->exec("CREATE TABLE test(id integer primary key)"); @@ -226,7 +226,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->assertEquals(2, $this->ch->querySingle($select)); } - function testCommitChainedTransactionsOutOfOrder() { + public function testCommitChainedTransactionsOutOfOrder() { $select = "SELECT count(*) FROM test"; $insert = "INSERT INTO test(id) values(null)"; $this->drv->exec("CREATE TABLE test(id integer primary key)"); @@ -243,7 +243,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $tr2->commit(); } - function testRollbackChainedTransactions() { + public function testRollbackChainedTransactions() { $select = "SELECT count(*) FROM test"; $insert = "INSERT INTO test(id) values(null)"; $this->drv->exec("CREATE TABLE test(id integer primary key)"); @@ -263,7 +263,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->assertEquals(0, $this->ch->querySingle($select)); } - function testRollbackChainedTransactionsOutOfOrder() { + public function testRollbackChainedTransactionsOutOfOrder() { $select = "SELECT count(*) FROM test"; $insert = "INSERT INTO test(id) values(null)"; $this->drv->exec("CREATE TABLE test(id integer primary key)"); @@ -283,7 +283,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->assertEquals(0, $this->ch->querySingle($select)); } - function testPartiallyRollbackChainedTransactions() { + public function testPartiallyRollbackChainedTransactions() { $select = "SELECT count(*) FROM test"; $insert = "INSERT INTO test(id) values(null)"; $this->drv->exec("CREATE TABLE test(id integer primary key)"); @@ -303,7 +303,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->assertEquals(1, $this->ch->querySingle($select)); } - function testFetchSchemaVersion() { + public function testFetchSchemaVersion() { $this->assertSame(0, $this->drv->schemaVersion()); $this->drv->exec("PRAGMA user_version=1"); $this->assertSame(1, $this->drv->schemaVersion()); @@ -311,17 +311,17 @@ class TestDbDriverSQLite3 extends Test\AbstractTest { $this->assertSame(2, $this->drv->schemaVersion()); } - function testLockTheDatabase() { + public function testLockTheDatabase() { $this->drv->savepointCreate(true); $this->assertException(); $this->ch->exec("CREATE TABLE test(id integer primary key)"); } - function testUnlockTheDatabase() { + public function testUnlockTheDatabase() { $this->drv->savepointCreate(true); $this->drv->savepointRelease(); $this->drv->savepointCreate(true); $this->drv->savepointUndo(); $this->assertSame(true, $this->ch->exec("CREATE TABLE test(id integer primary key)")); } -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/TestDbResultSQLite3.php b/tests/Db/SQLite3/TestDbResultSQLite3.php index f52754c..3d92b54 100644 --- a/tests/Db/SQLite3/TestDbResultSQLite3.php +++ b/tests/Db/SQLite3/TestDbResultSQLite3.php @@ -4,11 +4,10 @@ namespace JKingWeb\Arsse; /** @covers \JKingWeb\Arsse\Db\SQLite3\Result */ class TestDbResultSQLite3 extends Test\AbstractTest { - protected $c; - function setUp() { - if(!extension_loaded("sqlite3")) { + public function setUp() { + if (!extension_loaded("sqlite3")) { $this->markTestSkipped("SQLite extension not loaded"); } $c = new \SQLite3(":memory:"); @@ -16,49 +15,49 @@ class TestDbResultSQLite3 extends Test\AbstractTest { $this->c = $c; } - function tearDown() { + public function tearDown() { $this->c->close(); unset($this->c); } - function testConstructResult() { + public function testConstructResult() { $set = $this->c->query("SELECT 1"); $this->assertInstanceOf(Db\Result::class, new Db\SQLite3\Result($set)); } - function testGetChangeCountAndLastInsertId() { + public function testGetChangeCountAndLastInsertId() { $this->c->query("CREATE TABLE test(col)"); $set = $this->c->query("INSERT INTO test(col) values(1)"); $rows = $this->c->changes(); $id = $this->c->lastInsertRowID(); - $r = new Db\SQLite3\Result($set,[$rows,$id]); + $r = new Db\SQLite3\Result($set, [$rows,$id]); $this->assertEquals($rows, $r->changes()); $this->assertEquals($id, $r->lastId()); } - function testIterateOverResults() { + public function testIterateOverResults() { $set = $this->c->query("SELECT 1 as col union select 2 as col union select 3 as col"); $rows = []; - foreach(new Db\SQLite3\Result($set) as $index => $row) { + foreach (new Db\SQLite3\Result($set) as $index => $row) { $rows[$index] = $row['col']; } $this->assertEquals([0 => 1, 1 => 2, 2 => 3], $rows); } - function testIterateOverResultsTwice() { + public function testIterateOverResultsTwice() { $set = $this->c->query("SELECT 1 as col union select 2 as col union select 3 as col"); $rows = []; $test = new Db\SQLite3\Result($set); - foreach($test as $row) { + foreach ($test as $row) { $rows[] = $row['col']; } - foreach($test as $row) { + foreach ($test as $row) { $rows[] = $row['col']; } $this->assertEquals([1,2,3,1,2,3], $rows); } - function testGetSingleValues() { + public function testGetSingleValues() { $set = $this->c->query("SELECT 1867 as year union select 1970 as year union select 2112 as year"); $test = new Db\SQLite3\Result($set); $this->assertEquals(1867, $test->getValue()); @@ -67,7 +66,7 @@ class TestDbResultSQLite3 extends Test\AbstractTest { $this->assertSame(null, $test->getValue()); } - function testGetFirstValuesOnly() { + public function testGetFirstValuesOnly() { $set = $this->c->query("SELECT 1867 as year, 19 as century union select 1970 as year, 20 as century union select 2112 as year, 22 as century"); $test = new Db\SQLite3\Result($set); $this->assertEquals(1867, $test->getValue()); @@ -76,7 +75,7 @@ class TestDbResultSQLite3 extends Test\AbstractTest { $this->assertSame(null, $test->getValue()); } - function testGetRows() { + public function testGetRows() { $set = $this->c->query("SELECT '2112' as album, '2112' as track union select 'Clockwork Angels' as album, 'The Wreckers' as track"); $rows = [ ['album' => '2112', 'track' => '2112'], @@ -88,4 +87,4 @@ class TestDbResultSQLite3 extends Test\AbstractTest { $this->assertSame(null, $test->getRow()); $this->assertEquals($rows, $test->getAll()); } -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/TestDbStatementSQLite3.php b/tests/Db/SQLite3/TestDbStatementSQLite3.php index 6135e8b..fcfef72 100644 --- a/tests/Db/SQLite3/TestDbStatementSQLite3.php +++ b/tests/Db/SQLite3/TestDbStatementSQLite3.php @@ -1,21 +1,21 @@ * @covers \JKingWeb\Arsse\Db\SQLite3\ExceptionBuilder */ class TestDbStatementSQLite3 extends Test\AbstractTest { use Test\Db\BindingTests; protected $c; - static protected $imp = Db\SQLite3\Statement::class; + protected static $imp = Db\SQLite3\Statement::class; - function setUp() { + public function setUp() { $this->clearData(); - if(!extension_loaded("sqlite3")) { + if (!extension_loaded("sqlite3")) { $this->markTestSkipped("SQLite extension not loaded"); } $c = new \SQLite3(":memory:"); @@ -23,7 +23,7 @@ class TestDbStatementSQLite3 extends Test\AbstractTest { $this->c = $c; } - function tearDown() { + public function tearDown() { $this->c->close(); unset($this->c); } @@ -32,7 +32,7 @@ class TestDbStatementSQLite3 extends Test\AbstractTest { $nativeStatement = $this->c->prepare("SELECT ? as value"); $s = new self::$imp($this->c, $nativeStatement); $types = array_unique(Statement::TYPES); - foreach($types as $type) { + foreach ($types as $type) { $s->rebindArray([$strict ? "strict $type" : $type]); $val = $s->runArray([$input])->getRow()['value']; $this->assertSame($expectations[$type], $val, "Binding from type $type failed comparison."); @@ -42,19 +42,19 @@ class TestDbStatementSQLite3 extends Test\AbstractTest { } } - function testConstructStatement() { + public function testConstructStatement() { $nativeStatement = $this->c->prepare("SELECT ? as value"); $this->assertInstanceOf(Statement::class, new Db\SQLite3\Statement($this->c, $nativeStatement)); } - function testBindMissingValue() { + public function testBindMissingValue() { $nativeStatement = $this->c->prepare("SELECT ? as value"); $s = new self::$imp($this->c, $nativeStatement); $val = $s->runArray()->getRow()['value']; $this->assertSame(null, $val); } - function testBindMultipleValues() { + public function testBindMultipleValues() { $exp = [ 'one' => 1, 'two' => 2, @@ -65,7 +65,7 @@ class TestDbStatementSQLite3 extends Test\AbstractTest { $this->assertSame($exp, $val); } - function testBindRecursively() { + public function testBindRecursively() { $exp = [ 'one' => 1, 'two' => 2, @@ -78,14 +78,14 @@ class TestDbStatementSQLite3 extends Test\AbstractTest { $this->assertSame($exp, $val); } - function testBindWithoutType() { + public function testBindWithoutType() { $nativeStatement = $this->c->prepare("SELECT ? as value"); $this->assertException("paramTypeMissing", "Db"); $s = new self::$imp($this->c, $nativeStatement, []); $s->runArray([1]); } - function testViolateConstraint() { + public function testViolateConstraint() { $this->c->exec("CREATE TABLE test(id integer not null)"); $nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)"); $s = new self::$imp($this->c, $nativeStatement, ["int"]); @@ -93,11 +93,11 @@ class TestDbStatementSQLite3 extends Test\AbstractTest { $s->runArray([null]); } - function testMismatchTypes() { + public function testMismatchTypes() { $this->c->exec("CREATE TABLE test(id integer primary key)"); $nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)"); $s = new self::$imp($this->c, $nativeStatement, ["str"]); $this->assertException("typeViolation", "Db", "ExceptionInput"); $s->runArray(['ook']); } -} \ No newline at end of file +} diff --git a/tests/Db/SQLite3/TestDbUpdateSQLite3.php b/tests/Db/SQLite3/TestDbUpdateSQLite3.php index 8946588..a71c605 100644 --- a/tests/Db/SQLite3/TestDbUpdateSQLite3.php +++ b/tests/Db/SQLite3/TestDbUpdateSQLite3.php @@ -1,10 +1,10 @@ * @covers \JKingWeb\Arsse\Db\SQLite3\ExceptionBuilder */ class TestDbUpdateSQLite3 extends Test\AbstractTest { @@ -16,13 +16,13 @@ class TestDbUpdateSQLite3 extends Test\AbstractTest { const MINIMAL1 = "create table arsse_meta(key text primary key not null, value text); pragma user_version=1"; const MINIMAL2 = "pragma user_version=2"; - function setUp(Conf $conf = null) { - if(!extension_loaded("sqlite3")) { + public function setUp(Conf $conf = null) { + if (!extension_loaded("sqlite3")) { $this->markTestSkipped("SQLite extension not loaded"); } $this->clearData(); $this->vfs = vfsStream::setup("schemata", null, ['SQLite3' => []]); - if(!$conf) { + if (!$conf) { $conf = new Conf(); } $conf->dbDriver = Db\SQLite3\Driver::class; @@ -33,68 +33,68 @@ class TestDbUpdateSQLite3 extends Test\AbstractTest { $this->drv = new Db\SQLite3\Driver(true); } - function tearDown() { + public function tearDown() { unset($this->drv); unset($this->data); unset($this->vfs); $this->clearData(); } - function testLoadMissingFile() { + public function testLoadMissingFile() { $this->assertException("updateFileMissing", "Db"); $this->drv->schemaUpdate(1, $this->base); } - function testLoadUnreadableFile() { + public function testLoadUnreadableFile() { touch($this->path."0.sql"); chmod($this->path."0.sql", 0000); $this->assertException("updateFileUnreadable", "Db"); $this->drv->schemaUpdate(1, $this->base); } - function testLoadCorruptFile() { + public function testLoadCorruptFile() { file_put_contents($this->path."0.sql", "This is a corrupt file"); $this->assertException("updateFileError", "Db"); $this->drv->schemaUpdate(1, $this->base); } - function testLoadIncompleteFile() { + public function testLoadIncompleteFile() { file_put_contents($this->path."0.sql", "create table arsse_meta(key text primary key not null, value text);"); $this->assertException("updateFileIncomplete", "Db"); $this->drv->schemaUpdate(1, $this->base); } - function testLoadCorrectFile() { + public function testLoadCorrectFile() { file_put_contents($this->path."0.sql", self::MINIMAL1); $this->drv->schemaUpdate(1, $this->base); $this->assertEquals(1, $this->drv->schemaVersion()); } - function testPerformPartialUpdate() { + public function testPerformPartialUpdate() { file_put_contents($this->path."0.sql", self::MINIMAL1); file_put_contents($this->path."1.sql", ""); $this->assertException("updateFileIncomplete", "Db"); try { $this->drv->schemaUpdate(2, $this->base); - } catch(Exception $e) { + } catch (Exception $e) { $this->assertEquals(1, $this->drv->schemaVersion()); throw $e; } } - function testPerformSequentialUpdate() { + public function testPerformSequentialUpdate() { file_put_contents($this->path."0.sql", self::MINIMAL1); file_put_contents($this->path."1.sql", self::MINIMAL2); $this->drv->schemaUpdate(2, $this->base); $this->assertEquals(2, $this->drv->schemaVersion()); } - function testPerformActualUpdate() { + public function testPerformActualUpdate() { $this->drv->schemaUpdate(Database::SCHEMA_VERSION); $this->assertEquals(Database::SCHEMA_VERSION, $this->drv->schemaVersion()); } - function testDeclineManualUpdate() { + public function testDeclineManualUpdate() { // turn auto-updating off $conf = new Conf(); $conf->dbAutoUpdate = false; @@ -103,8 +103,8 @@ class TestDbUpdateSQLite3 extends Test\AbstractTest { $this->drv->schemaUpdate(Database::SCHEMA_VERSION); } - function testDeclineDowngrade() { + public function testDeclineDowngrade() { $this->assertException("updateTooNew", "Db"); $this->drv->schemaUpdate(-1, $this->base); } -} \ No newline at end of file +} diff --git a/tests/Db/TestTransaction.php b/tests/Db/TestTransaction.php index 97f1ef6..d687460 100644 --- a/tests/Db/TestTransaction.php +++ b/tests/Db/TestTransaction.php @@ -1,6 +1,7 @@ clearData(); $drv = Phake::mock(Db\SQLite3\Driver::class); Phake::when($drv)->savepointRelease->thenReturn(true); @@ -18,7 +19,7 @@ class TestTransaction extends Test\AbstractTest { $this->drv = $drv; } - function testManipulateTransactions() { + public function testManipulateTransactions() { $tr1 = new Transaction($this->drv); $tr2 = new Transaction($this->drv); Phake::verify($this->drv, Phake::times(2))->savepointCreate; @@ -30,7 +31,7 @@ class TestTransaction extends Test\AbstractTest { Phake::verify($this->drv)->savepointUndo(2); } - function testCloseTransactions() { + public function testCloseTransactions() { $tr1 = new Transaction($this->drv); $tr2 = new Transaction($this->drv); $this->assertTrue($tr1->isPending()); @@ -45,7 +46,7 @@ class TestTransaction extends Test\AbstractTest { Phake::verify($this->drv)->savepointUndo(2); } - function testIgnoreRollbackErrors() { + public function testIgnoreRollbackErrors() { Phake::when($this->drv)->savepointUndo->thenThrow(new Db\ExceptionSavepoint("stale")); $tr1 = new Transaction($this->drv); $tr2 = new Transaction($this->drv); @@ -53,4 +54,4 @@ class TestTransaction extends Test\AbstractTest { Phake::verify($this->drv)->savepointUndo(1); Phake::verify($this->drv)->savepointUndo(2); } -} \ No newline at end of file +} diff --git a/tests/Exception/TestException.php b/tests/Exception/TestException.php index 3697fb5..83cc5eb 100644 --- a/tests/Exception/TestException.php +++ b/tests/Exception/TestException.php @@ -1,19 +1,19 @@ clearData(false); // create a mock Lang object so as not to create a dependency loop Arsse::$lang = Phake::mock(Lang::class); Phake::when(Arsse::$lang)->msg->thenReturn(""); } - function tearDown() { + public function tearDown() { // verify calls to the mock Lang object Phake::verify(Arsse::$lang, Phake::atLeast(0))->msg($this->isType("string"), $this->anything()); Phake::verifyNoOtherInteractions(Arsse::$lang); @@ -21,7 +21,7 @@ class TestException extends Test\AbstractTest { $this->clearData(true); } - function testBaseClass() { + public function testBaseClass() { $this->assertException("unknown"); throw new Exception("unknown"); } @@ -29,7 +29,7 @@ class TestException extends Test\AbstractTest { /** * @depends testBaseClass */ - function testBaseClassWithoutMessage() { + public function testBaseClassWithoutMessage() { $this->assertException("unknown"); throw new Exception(); } @@ -37,7 +37,7 @@ class TestException extends Test\AbstractTest { /** * @depends testBaseClass */ - function testDerivedClass() { + public function testDerivedClass() { $this->assertException("fileMissing", "Lang"); throw new Lang\Exception("fileMissing"); } @@ -45,7 +45,7 @@ class TestException extends Test\AbstractTest { /** * @depends testDerivedClass */ - function testDerivedClassWithMessageParameters() { + public function testDerivedClassWithMessageParameters() { $this->assertException("fileMissing", "Lang"); throw new Lang\Exception("fileMissing", "en"); } @@ -53,7 +53,7 @@ class TestException extends Test\AbstractTest { /** * @depends testBaseClass */ - function testBaseClassWithUnknownCode() { + public function testBaseClassWithUnknownCode() { $this->assertException("uncoded"); throw new Exception("testThisExceptionMessageDoesNotExist"); } @@ -61,7 +61,7 @@ class TestException extends Test\AbstractTest { /** * @depends testBaseClassWithUnknownCode */ - function testDerivedClassWithMissingMessage() { + public function testDerivedClassWithMissingMessage() { $this->assertException("uncoded"); throw new Lang\Exception("testThisExceptionMessageDoesNotExist"); } diff --git a/tests/Feed/TestFeed.php b/tests/Feed/TestFeed.php index 56ae7ac..7c3e289 100644 --- a/tests/Feed/TestFeed.php +++ b/tests/Feed/TestFeed.php @@ -1,10 +1,10 @@ markTestSkipped("Test Web server is not accepting requests"); } $this->base = self::$host."Feed/"; @@ -90,7 +90,7 @@ class TestFeed extends Test\AbstractTest { Arsse::$db = Phake::mock(Database::class); } - function testParseAFeed() { + public function testParseAFeed() { // test that various properties are set on the feed and on items $f = new Feed(null, $this->base."Parsing/Valid"); $this->assertTrue(isset($f->lastModified)); @@ -133,27 +133,27 @@ class TestFeed extends Test\AbstractTest { $this->assertSame($categories, $f->data->items[5]->categories); } - function testParseEntityExpansionAttack() { + public function testParseEntityExpansionAttack() { $this->assertException("xmlEntity", "Feed"); new Feed(null, $this->base."Parsing/XEEAttack"); } - function testParseExternalEntityAttack() { + public function testParseExternalEntityAttack() { $this->assertException("xmlEntity", "Feed"); new Feed(null, $this->base."Parsing/XXEAttack"); } - function testParseAnUnsupportedFeed() { + public function testParseAnUnsupportedFeed() { $this->assertException("unsupportedFeedFormat", "Feed"); new Feed(null, $this->base."Parsing/Unsupported"); } - function testParseAMalformedFeed() { + public function testParseAMalformedFeed() { $this->assertException("malformedXml", "Feed"); new Feed(null, $this->base."Parsing/Malformed"); } - function testDeduplicateFeedItems() { + public function testDeduplicateFeedItems() { // duplicates with dates lead to the newest match being kept $t = strtotime("2002-05-19T15:21:36Z"); $f = new Feed(null, $this->base."Deduplication/Permalink-Dates"); @@ -180,7 +180,7 @@ class TestFeed extends Test\AbstractTest { $this->assertSame("http://example.com/1", $f->newItems[0]->url); } - function testHandleCacheHeadersOn304() { + public function testHandleCacheHeadersOn304() { // upon 304, the client should re-use the caching header values it supplied the server $t = time(); $e = "78567a"; @@ -198,7 +198,7 @@ class TestFeed extends Test\AbstractTest { $this->assertSame($e, $f->resource->getETag()); } - function testHandleCacheHeadersOn200() { + public function testHandleCacheHeadersOn200() { // these tests should trust the server-returned time, even in cases of obviously incorrect results $t = time() - 2000; $f = new Feed(null, $this->base."Caching/200Past"); @@ -226,11 +226,11 @@ class TestFeed extends Test\AbstractTest { $this->assertTime($t, $f->lastModified); } - function testComputeNextFetchOnError() { - for($a = 0; $a < 100; $a++) { - if($a < 3) { + public function testComputeNextFetchOnError() { + for ($a = 0; $a < 100; $a++) { + if ($a < 3) { $this->assertTime("now + 5 minutes", Feed::nextFetchOnError($a)); - } else if($a < 15) { + } elseif ($a < 15) { $this->assertTime("now + 3 hours", Feed::nextFetchOnError($a)); } else { $this->assertTime("now + 1 day", Feed::nextFetchOnError($a)); @@ -238,7 +238,7 @@ class TestFeed extends Test\AbstractTest { } } - function testComputeNextFetchFrom304() { + public function testComputeNextFetchFrom304() { // if less than half an hour, check in 15 minutes $t = strtotime("now"); $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); @@ -286,7 +286,7 @@ class TestFeed extends Test\AbstractTest { $this->assertTime($exp, $f->nextFetch); } - function testComputeNextFetchFrom200() { + public function testComputeNextFetchFrom200() { // if less than half an hour, check in 15 minutes $f = new Feed(null, $this->base."NextFetch/30m"); $exp = strtotime("now + 15 minutes"); @@ -313,7 +313,7 @@ class TestFeed extends Test\AbstractTest { $this->assertTime($exp, $f->nextFetch); } - function testMatchLatestArticles() { + public function testMatchLatestArticles() { Phake::when(Arsse::$db)->feedMatchLatest(1, $this->anything())->thenReturn(new Test\Result($this->latest)); $f = new Feed(1, $this->base."Matching/1"); $this->assertCount(0, $f->newItems); @@ -329,15 +329,15 @@ class TestFeed extends Test\AbstractTest { $this->assertCount(2, $f->changedItems); } - function testMatchHistoricalArticles() { + public function testMatchHistoricalArticles() { Phake::when(Arsse::$db)->feedMatchLatest(1, $this->anything())->thenReturn(new Test\Result($this->latest)); Phake::when(Arsse::$db)->feedMatchIds(1, $this->anything(), $this->anything(), $this->anything(), $this->anything())->thenReturn(new Test\Result($this->others)); $f = new Feed(1, $this->base."Matching/5"); $this->assertCount(0, $f->newItems); - $this->assertCount(0, $f->changedItems); + $this->assertCount(0, $f->changedItems); } - function testScrapeFullContent() { + public function testScrapeFullContent() { // first make sure that the absence of scraping works as expected $f = new Feed(null, $this->base."Scraping/Feed"); $exp = "

Partial content

"; @@ -347,4 +347,4 @@ class TestFeed extends Test\AbstractTest { $exp = "

Partial content, followed by more content

"; $this->assertSame($exp, $f->newItems[0]->content); } -} \ No newline at end of file +} diff --git a/tests/Feed/TestFeedFetching.php b/tests/Feed/TestFeedFetching.php index 3bad23a..127f768 100644 --- a/tests/Feed/TestFeedFetching.php +++ b/tests/Feed/TestFeedFetching.php @@ -1,18 +1,18 @@ markTestSkipped("Feed fetching tests are only accurate with curl enabled."); - } else if(!@file_get_contents(self::$host."IsUp")) { + } elseif (!@file_get_contents(self::$host."IsUp")) { $this->markTestSkipped("Test Web server is not accepting requests"); } $this->base = self::$host."Feed/"; @@ -20,50 +20,50 @@ class TestFeedFetching extends Test\AbstractTest { Arsse::$conf = new Conf(); } - function testHandle400() { + public function testHandle400() { $this->assertException("unsupportedFeedFormat", "Feed"); new Feed(null, $this->base."Fetching/Error?code=400"); } - function testHandle401() { + public function testHandle401() { $this->assertException("unauthorized", "Feed"); new Feed(null, $this->base."Fetching/Error?code=401"); } - function testHandle403() { + public function testHandle403() { $this->assertException("forbidden", "Feed"); new Feed(null, $this->base."Fetching/Error?code=403"); } - function testHandle404() { + public function testHandle404() { $this->assertException("invalidUrl", "Feed"); new Feed(null, $this->base."Fetching/Error?code=404"); } - function testHandle500() { + public function testHandle500() { $this->assertException("unsupportedFeedFormat", "Feed"); new Feed(null, $this->base."Fetching/Error?code=500"); } - function testHandleARedirectLoop() { + public function testHandleARedirectLoop() { $this->assertException("maxRedirect", "Feed"); new Feed(null, $this->base."Fetching/EndlessLoop?i=0"); } - function testHandleATimeout() { + public function testHandleATimeout() { Arsse::$conf->fetchTimeout = 1; $this->assertException("timeout", "Feed"); new Feed(null, $this->base."Fetching/Timeout"); } - function testHandleAnOverlyLargeFeed() { + public function testHandleAnOverlyLargeFeed() { Arsse::$conf->fetchSizeLimit = 512; $this->assertException("maxSize", "Feed"); new Feed(null, $this->base."Fetching/TooLarge"); } - function testHandleACertificateError() { + public function testHandleACertificateError() { $this->assertException("invalidCertificate", "Feed"); new Feed(null, "https://localhost:8000/"); } -} \ No newline at end of file +} diff --git a/tests/Lang/TestLang.php b/tests/Lang/TestLang.php index 63ec7bd..4a24d56 100644 --- a/tests/Lang/TestLang.php +++ b/tests/Lang/TestLang.php @@ -1,6 +1,7 @@ assertCount(sizeof($this->files), $this->l->list("en")); } /** * @depends testListLanguages */ - function testSetLanguage() { + public function testSetLanguage() { $this->assertEquals("en", $this->l->set("en")); $this->assertEquals("en_ca", $this->l->set("en_ca")); $this->assertEquals("de", $this->l->set("de_ch")); @@ -31,7 +32,7 @@ class TestLang extends Test\AbstractTest { /** * @depends testSetLanguage */ - function testLoadInternalStrings() { + public function testLoadInternalStrings() { $this->assertEquals("", $this->l->set("", true)); $this->assertCount(sizeof(Lang::REQUIRED), $this->l->dump()); } @@ -39,7 +40,7 @@ class TestLang extends Test\AbstractTest { /** * @depends testLoadInternalStrings */ - function testLoadDefaultLanguage() { + public function testLoadDefaultLanguage() { $this->assertEquals(Lang::DEFAULT, $this->l->set(Lang::DEFAULT, true)); $str = $this->l->dump(); $this->assertArrayHasKey('Exception.JKingWeb/Arsse/Exception.uncoded', $str); @@ -49,7 +50,7 @@ class TestLang extends Test\AbstractTest { /** * @depends testLoadDefaultLanguage */ - function testLoadSupplementaryLanguage() { + public function testLoadSupplementaryLanguage() { $this->l->set(Lang::DEFAULT, true); $this->assertEquals("ja", $this->l->set("ja", true)); $str = $this->l->dump(); @@ -57,5 +58,4 @@ class TestLang extends Test\AbstractTest { $this->assertArrayHasKey('Test.presentText', $str); $this->assertArrayHasKey('Test.absentText', $str); } - -} \ No newline at end of file +} diff --git a/tests/Lang/TestLangErrors.php b/tests/Lang/TestLangErrors.php index bdf5338..2f177c2 100644 --- a/tests/Lang/TestLangErrors.php +++ b/tests/Lang/TestLangErrors.php @@ -1,6 +1,7 @@ l->set("", true); } - function testLoadEmptyFile() { + public function testLoadEmptyFile() { $this->assertException("fileCorrupt", "Lang"); $this->l->set("fr_ca", true); } - function testLoadFileWhichDoesNotReturnAnArray() { + public function testLoadFileWhichDoesNotReturnAnArray() { $this->assertException("fileCorrupt", "Lang"); $this->l->set("it", true); } - function testLoadFileWhichIsNotPhp() { + public function testLoadFileWhichIsNotPhp() { $this->assertException("fileCorrupt", "Lang"); $this->l->set("ko", true); } - function testLoadFileWhichIsCorrupt() { + public function testLoadFileWhichIsCorrupt() { $this->assertException("fileCorrupt", "Lang"); $this->l->set("zh", true); } - function testLoadFileWithooutReadPermission() { + public function testLoadFileWithooutReadPermission() { $this->assertException("fileUnreadable", "Lang"); $this->l->set("ru", true); } - function testLoadSubtagOfMissingLanguage() { + public function testLoadSubtagOfMissingLanguage() { $this->assertException("fileMissing", "Lang"); $this->l->set("pt_br", true); } - function testFetchInvalidMessage() { + public function testFetchInvalidMessage() { $this->assertException("stringInvalid", "Lang"); $this->l->set("vi", true); $txt = $this->l->msg('Test.presentText'); } - function testFetchMissingMessage() { + public function testFetchMissingMessage() { $this->assertException("stringMissing", "Lang"); $txt = $this->l->msg('Test.absentText'); } - function testLoadMissingDefaultLanguage() { + public function testLoadMissingDefaultLanguage() { unlink($this->path.Lang::DEFAULT.".php"); $this->assertException("defaultFileMissing", "Lang"); $this->l->set("fr", true); } -} \ No newline at end of file +} diff --git a/tests/Lang/testLangComplex.php b/tests/Lang/testLangComplex.php index 763e125..99c6b54 100644 --- a/tests/Lang/testLangComplex.php +++ b/tests/Lang/testLangComplex.php @@ -1,6 +1,7 @@ l->set(Lang::DEFAULT, true); } - function testLazyLoad() { + public function testLazyLoad() { $this->l->set("ja"); $this->assertArrayNotHasKey('Test.absentText', $this->l->dump()); } @@ -23,14 +24,14 @@ class TestLangComplex extends Test\AbstractTest { /** * @depends testLazyLoad */ - function testGetWantedAndLoadedLocale() { + public function testGetWantedAndLoadedLocale() { $this->l->set("en", true); $this->l->set("ja"); $this->assertEquals("ja", $this->l->get()); $this->assertEquals("en", $this->l->get(true)); } - function testLoadCascadeOfFiles() { + public function testLoadCascadeOfFiles() { $this->l->set("ja", true); $this->assertEquals("de", $this->l->set("de", true)); $str = $this->l->dump(); @@ -41,11 +42,11 @@ class TestLangComplex extends Test\AbstractTest { /** * @depends testLoadCascadeOfFiles */ - function testLoadSubtag() { + public function testLoadSubtag() { $this->assertEquals("en_ca", $this->l->set("en_ca", true)); } - function testFetchAMessage() { + public function testFetchAMessage() { $this->l->set("de", true); $this->assertEquals('und der Stein der Weisen', $this->l->msg('Test.presentText')); } @@ -53,7 +54,7 @@ class TestLangComplex extends Test\AbstractTest { /** * @depends testFetchAMessage */ - function testFetchAMessageWithMissingParameters() { + public function testFetchAMessageWithMissingParameters() { $this->l->set("en_ca", true); $this->assertEquals('{0} and {1}', $this->l->msg('Test.presentText')); } @@ -61,7 +62,7 @@ class TestLangComplex extends Test\AbstractTest { /** * @depends testFetchAMessage */ - function testFetchAMessageWithSingleNumericParameter() { + public function testFetchAMessageWithSingleNumericParameter() { $this->l->set("en_ca", true); $this->assertEquals('Default language file "en" missing', $this->l->msg('Exception.JKingWeb/Arsse/Lang/Exception.defaultFileMissing', Lang::DEFAULT)); } @@ -69,7 +70,7 @@ class TestLangComplex extends Test\AbstractTest { /** * @depends testFetchAMessage */ - function testFetchAMessageWithMultipleNumericParameters() { + public function testFetchAMessageWithMultipleNumericParameters() { $this->l->set("en_ca", true); $this->assertEquals('Happy Rotter and the Philosopher\'s Stone', $this->l->msg('Test.presentText', ['Happy Rotter', 'the Philosopher\'s Stone'])); } @@ -77,14 +78,14 @@ class TestLangComplex extends Test\AbstractTest { /** * @depends testFetchAMessage */ - function testFetchAMessageWithNamedParameters() { + public function testFetchAMessageWithNamedParameters() { $this->assertEquals('Message string "Test.absentText" missing from all loaded language files (en)', $this->l->msg('Exception.JKingWeb/Arsse/Lang/Exception.stringMissing', ['msgID' => 'Test.absentText', 'fileList' => 'en'])); } /** * @depends testFetchAMessage */ - function testReloadDefaultStrings() { + public function testReloadDefaultStrings() { $this->l->set("de", true); $this->l->set("en", true); $this->assertEquals('and the Philosopher\'s Stone', $this->l->msg('Test.presentText')); @@ -93,11 +94,11 @@ class TestLangComplex extends Test\AbstractTest { /** * @depends testFetchAMessage */ - function testReloadGeneralTagAfterSubtag() { + public function testReloadGeneralTagAfterSubtag() { $this->l->set("en", true); $this->l->set("en_us", true); $this->assertEquals('and the Sorcerer\'s Stone', $this->l->msg('Test.presentText')); $this->l->set("en", true); $this->assertEquals('and the Philosopher\'s Stone', $this->l->msg('Test.presentText')); } -} \ No newline at end of file +} diff --git a/tests/Misc/TestContext.php b/tests/Misc/TestContext.php index d161513..f03ca41 100644 --- a/tests/Misc/TestContext.php +++ b/tests/Misc/TestContext.php @@ -1,15 +1,15 @@ getMethods(\ReflectionMethod::IS_PUBLIC) as $m) { - if($m->isConstructor() || $m->isStatic()) { + foreach ((new \ReflectionObject($c))->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) { + if ($m->isConstructor() || $m->isStatic()) { continue; } $method = $m->name; @@ -18,7 +18,7 @@ class TestContext extends Test\AbstractTest { } } - function testSetContextOptions() { + public function testSetContextOptions() { $v = [ 'reverse' => true, 'limit' => 10, @@ -38,15 +38,15 @@ class TestContext extends Test\AbstractTest { ]; $times = ['modifiedSince','notModifiedSince']; $c = new Context; - foreach((new \ReflectionObject($c))->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) { - if($m->isConstructor() || $m->isStatic()) { + foreach ((new \ReflectionObject($c))->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) { + if ($m->isConstructor() || $m->isStatic()) { continue; } $method = $m->name; $this->assertArrayHasKey($method, $v, "Context method $method not included in test"); $this->assertInstanceOf(Context::class, $c->$method($v[$method])); $this->assertTrue($c->$method()); - if(in_array($method, $times)) { + if (in_array($method, $times)) { $this->assertTime($c->$method, $v[$method]); } else { $this->assertSame($c->$method, $v[$method]); @@ -54,13 +54,13 @@ class TestContext extends Test\AbstractTest { } } - function testCleanArrayValues() { + public function testCleanArrayValues() { $methods = ["articles", "editions"]; $in = [1, "2", 3.5, 3.0, "ook", 0, -20, true, false, null, new \DateTime(), -1.0]; $out = [1,2, 3]; $c = new Context; - foreach($methods as $method) { + foreach ($methods as $method) { $this->assertSame($out, $c->$method($in)->$method, "Context method $method did not return the expected results"); } } -} \ No newline at end of file +} diff --git a/tests/REST/NextCloudNews/TestNCNV1_2.php b/tests/REST/NextCloudNews/TestNCNV1_2.php index 6ff2f3b..bd78bb9 100644 --- a/tests/REST/NextCloudNews/TestNCNV1_2.php +++ b/tests/REST/NextCloudNews/TestNCNV1_2.php @@ -1,6 +1,7 @@ clearData(); Arsse::$conf = new Conf(); // create a mock user manager @@ -268,16 +269,16 @@ class TestNCNV1_2 extends Test\AbstractTest { Phake::when(Arsse::$user)->rightsGet->thenReturn(100); Arsse::$user->id = "john.doe@example.com"; // create a mock database interface - Arsse::$db = Phake::mock(Database::Class); + Arsse::$db = Phake::mock(Database::class); Phake::when(Arsse::$db)->begin->thenReturn(Phake::mock(Transaction::class)); $this->h = new REST\NextCloudNews\V1_2(); } - function tearDown() { + public function tearDown() { $this->clearData(); } - function testRespondToInvalidPaths() { + public function testRespondToInvalidPaths() { $errs = [ 501 => [ ['GET', "/"], @@ -309,34 +310,34 @@ class TestNCNV1_2 extends Test\AbstractTest { ], ], ]; - foreach($errs[501] as $req) { + foreach ($errs[501] as $req) { $exp = new Response(501); list($method, $path) = $req; $this->assertEquals($exp, $this->h->dispatch(new Request($method, $path)), "$method call to $path did not return 501."); } - foreach($errs[405] as $allow => $cases) { + foreach ($errs[405] as $allow => $cases) { $exp = new Response(405, "", "", ['Allow: '.$allow]); - foreach($cases as $req) { + foreach ($cases as $req) { list($method, $path) = $req; $this->assertEquals($exp, $this->h->dispatch(new Request($method, $path)), "$method call to $path did not return 405."); } } } - function testRespondToInvalidInputTypes() { + public function testRespondToInvalidInputTypes() { $exp = new Response(415, "", "", ['Accept: application/json']); $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", '', 'application/xml'))); $exp = new Response(400); $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", '', 'application/json'))); } - function testReceiveAuthenticationChallenge() { + public function testReceiveAuthenticationChallenge() { Phake::when(Arsse::$user)->authHTTP->thenReturn(false); $exp = new Response(401, "", "", ['WWW-Authenticate: Basic realm="'.REST\NextCloudNews\V1_2::REALM.'"']); $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/"))); } - function testListFolders() { + public function testListFolders() { $list = [ ['id' => 1, 'name' => "Software", 'parent' => null], ['id' => 12, 'name' => "Hardware", 'parent' => null], @@ -348,7 +349,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/folders"))); } - function testAddAFolder() { + public function testAddAFolder() { $in = [ ["name" => "Software"], ["name" => "Hardware"], @@ -387,7 +388,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", json_encode($in[1]), 'application/json'))); } - function testRemoveAFolder() { + public function testRemoveAFolder() { Phake::when(Arsse::$db)->folderRemove(Arsse::$user->id, 1)->thenReturn(true)->thenThrow(new ExceptionInput("subjectMissing")); $exp = new Response(204); $this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/1"))); @@ -397,7 +398,7 @@ class TestNCNV1_2 extends Test\AbstractTest { Phake::verify(Arsse::$db, Phake::times(2))->folderRemove(Arsse::$user->id, 1); } - function testRenameAFolder() { + public function testRenameAFolder() { $in = [ ["name" => "Software"], ["name" => "Software"], @@ -425,7 +426,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/3", json_encode($in[0]), 'application/json'))); } - function testRetrieveServerVersion() { + public function testRetrieveServerVersion() { $exp = new Response(200, [ 'arsse_version' => \JKingWeb\Arsse\VERSION, 'version' => REST\NextCloudNews\V1_2::VERSION, @@ -433,7 +434,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/version"))); } - function testListSubscriptions() { + public function testListSubscriptions() { $exp1 = [ 'feeds' => [], 'starredCount' => 0, @@ -452,7 +453,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds"))); } - function testAddASubscription() { + public function testAddASubscription() { $in = [ ['url' => "http://example.com/news.atom", 'folderId' => 3], ['url' => "http://example.org/news.atom", 'folderId' => 8], @@ -467,13 +468,13 @@ class TestNCNV1_2 extends Test\AbstractTest { ]; // set up the necessary mocks Phake::when(Arsse::$db)->subscriptionAdd(Arsse::$user->id, "http://example.com/news.atom")->thenReturn(2112)->thenThrow(new ExceptionInput("constraintViolation")); // error on the second call - Phake::when(Arsse::$db)->subscriptionAdd(Arsse::$user->id, "http://example.org/news.atom")->thenReturn( 42 )->thenThrow(new ExceptionInput("constraintViolation")); // error on the second call + Phake::when(Arsse::$db)->subscriptionAdd(Arsse::$user->id, "http://example.org/news.atom")->thenReturn(42)->thenThrow(new ExceptionInput("constraintViolation")); // error on the second call Phake::when(Arsse::$db)->subscriptionPropertiesGet(Arsse::$user->id, 2112)->thenReturn($this->feeds['db'][0]); - Phake::when(Arsse::$db)->subscriptionPropertiesGet(Arsse::$user->id, 42)->thenReturn($this->feeds['db'][1]); + Phake::when(Arsse::$db)->subscriptionPropertiesGet(Arsse::$user->id, 42)->thenReturn($this->feeds['db'][1]); Phake::when(Arsse::$db)->editionLatest(Arsse::$user->id, (new Context)->subscription(2112))->thenReturn(0); - Phake::when(Arsse::$db)->editionLatest(Arsse::$user->id, (new Context)->subscription( 42))->thenReturn(4758915); + Phake::when(Arsse::$db)->editionLatest(Arsse::$user->id, (new Context)->subscription(42))->thenReturn(4758915); Phake::when(Arsse::$db)->subscriptionPropertiesSet(Arsse::$user->id, 2112, ['folder' => 3])->thenThrow(new ExceptionInput("idMissing")); // folder ID 3 does not exist - Phake::when(Arsse::$db)->subscriptionPropertiesSet(Arsse::$user->id, 42, ['folder' => 8])->thenReturn(true); + Phake::when(Arsse::$db)->subscriptionPropertiesSet(Arsse::$user->id, 42, ['folder' => 8])->thenReturn(true); // set up a mock for a bad feed Phake::when(Arsse::$db)->subscriptionAdd(Arsse::$user->id, "http://example.net/news.atom")->thenThrow(new \JKingWeb\Arsse\Feed\Exception("http://example.net/news.atom", new \PicoFeed\Client\InvalidUrlException())); // add the subscriptions @@ -494,7 +495,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[3]), 'application/json'))); } - function testRemoveASubscription() { + public function testRemoveASubscription() { Phake::when(Arsse::$db)->subscriptionRemove(Arsse::$user->id, 1)->thenReturn(true)->thenThrow(new ExceptionInput("subjectMissing")); $exp = new Response(204); $this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/feeds/1"))); @@ -504,7 +505,7 @@ class TestNCNV1_2 extends Test\AbstractTest { Phake::verify(Arsse::$db, Phake::times(2))->subscriptionRemove(Arsse::$user->id, 1); } - function testMoveASubscription() { + public function testMoveASubscription() { $in = [ ['folderId' => 0], ['folderId' => 42], @@ -528,7 +529,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[4]), 'application/json'))); } - function testRenameASubscription() { + public function testRenameASubscription() { $in = [ ['feedTitle' => null], ['feedTitle' => "Ook"], @@ -558,7 +559,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[6]), 'application/json'))); } - function testListStaleFeeds() { + public function testListStaleFeeds() { $out = [ [ 'id' => 42, @@ -569,7 +570,7 @@ class TestNCNV1_2 extends Test\AbstractTest { 'userId' => "", ], ]; - Phake::when(Arsse::$db)->feedListStale->thenReturn(array_column($out,"id")); + Phake::when(Arsse::$db)->feedListStale->thenReturn(array_column($out, "id")); $exp = new Response(200, ['feeds' => $out]); $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds/all"))); // retrieving the list when not an admin fails @@ -578,14 +579,14 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds/all"))); } - function testUpdateAFeed() { + public function testUpdateAFeed() { $in = [ ['feedId' => 42], // valid ['feedId' => 2112], // feed does not exist ['feedId' => "ook"], // invalid ID ['feed' => 42], // invalid input ]; - Phake::when(Arsse::$db)->feedUpdate( 42)->thenReturn(true); + Phake::when(Arsse::$db)->feedUpdate(42)->thenReturn(true); Phake::when(Arsse::$db)->feedUpdate(2112)->thenThrow(new ExceptionInput("subjectMissing")); $exp = new Response(204); $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[0]), 'application/json'))); @@ -601,7 +602,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[0]), 'application/json'))); } - function testListArticles() { + public function testListArticles() { $res = new Result($this->articles['db']); $t = new \DateTime; $in = [ @@ -648,7 +649,7 @@ class TestNCNV1_2 extends Test\AbstractTest { Phake::verify(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->reverse(true)->limit(5)); } - function testMarkAFolderRead() { + public function testMarkAFolderRead() { $read = ['read' => true]; $in = json_encode(['newestItemId' => 2112]); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->folder(1)->latestEdition(2112))->thenReturn(true); @@ -663,7 +664,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/42/read", $in, 'application/json'))); } - function testMarkASubscriptionRead() { + public function testMarkASubscriptionRead() { $read = ['read' => true]; $in = json_encode(['newestItemId' => 2112]); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->subscription(1)->latestEdition(2112))->thenReturn(true); @@ -678,7 +679,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/42/read", $in, 'application/json'))); } - function testMarkAllItemsRead() { + public function testMarkAllItemsRead() { $read = ['read' => true]; $in = json_encode(['newestItemId' => 2112]); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->latestEdition(2112))->thenReturn(true); @@ -690,7 +691,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/items/read?newestItemId=ook"))); } - function testChangeMarksOfASingleArticle() { + public function testChangeMarksOfASingleArticle() { $read = ['read' => true]; $unread = ['read' => false]; $star = ['starred' => true]; @@ -716,20 +717,20 @@ class TestNCNV1_2 extends Test\AbstractTest { Phake::verify(Arsse::$db, Phake::times(8))->articleMark(Arsse::$user->id, $this->anything(), $this->anything()); } - function testChangeMarksOfMultipleArticles() { + public function testChangeMarksOfMultipleArticles() { $read = ['read' => true]; $unread = ['read' => false]; $star = ['starred' => true]; $unstar = ['starred' => false]; $in = [ ["ook","eek","ack"], - range(100,199), - range(100,149), - range(150,199), + range(100, 199), + range(100, 149), + range(150, 199), ]; $inStar = $in; - for($a = 0; $a < sizeof($inStar); $a++) { - for($b = 0; $b < sizeof($inStar[$a]); $b++) { + for ($a = 0; $a < sizeof($inStar); $a++) { + for ($b = 0; $b < sizeof($inStar[$a]); $b++) { $inStar[$a][$b] = ['feedId' => 2112, 'guidHash' => $inStar[$a][$b]]; } } @@ -783,7 +784,7 @@ class TestNCNV1_2 extends Test\AbstractTest { Phake::verify(Arsse::$db)->articleMark(Arsse::$user->id, $unstar, (new Context)->articles($in[3])); } - function testQueryTheServerStatus() { + public function testQueryTheServerStatus() { $interval = Service::interval(); $valid = (new \DateTimeImmutable("now", new \DateTimezone("UTC")))->sub($interval); $invalid = $valid->sub($interval)->sub($interval); @@ -800,7 +801,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/status"))); } - function testCleanUpBeforeUpdate() { + public function testCleanUpBeforeUpdate() { Phake::when(Arsse::$db)->feedCleanup()->thenReturn(true); $exp = new Response(204); $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/before-update"))); @@ -811,7 +812,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/before-update"))); } - function testCleanUpAfterUpdate() { + public function testCleanUpAfterUpdate() { Phake::when(Arsse::$db)->articleCleanup()->thenReturn(true); $exp = new Response(204); $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/after-update"))); @@ -821,4 +822,4 @@ class TestNCNV1_2 extends Test\AbstractTest { $exp = new Response(403); $this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/after-update"))); } -} \ No newline at end of file +} diff --git a/tests/REST/NextCloudNews/TestNCNVersionDiscovery.php b/tests/REST/NextCloudNews/TestNCNVersionDiscovery.php index 07a307b..ad3f15a 100644 --- a/tests/REST/NextCloudNews/TestNCNVersionDiscovery.php +++ b/tests/REST/NextCloudNews/TestNCNVersionDiscovery.php @@ -1,16 +1,17 @@ clearData(); } - function testFetchVersionList() { + public function testFetchVersionList() { $exp = new Response(200, ['apiLevels' => ['v1-2']]); $h = new REST\NextCloudNews\Versions(); $req = new Request("GET", "/"); @@ -24,7 +25,7 @@ class TestNCNVersionDiscovery extends Test\AbstractTest { $this->assertEquals($exp, $res); } - function testUseIncorrectMethod() { + public function testUseIncorrectMethod() { $exp = new Response(405); $h = new REST\NextCloudNews\Versions(); $req = new Request("POST", "/"); @@ -32,11 +33,11 @@ class TestNCNVersionDiscovery extends Test\AbstractTest { $this->assertEquals($exp, $res); } - function testUseIncorrectPath() { + public function testUseIncorrectPath() { $exp = new Response(501); $h = new REST\NextCloudNews\Versions(); $req = new Request("GET", "/ook"); $res = $h->dispatch($req); $this->assertEquals($exp, $res); } -} \ No newline at end of file +} diff --git a/tests/Service/TestService.php b/tests/Service/TestService.php index 7f1f82d..0bd2d49 100644 --- a/tests/Service/TestService.php +++ b/tests/Service/TestService.php @@ -1,6 +1,7 @@ clearData(); Arsse::$conf = new Conf(); Arsse::$db = Phake::mock(Database::class); $this->srv = new Service(); } - function testComputeInterval() { + public function testComputeInterval() { $in = [ Arsse::$conf->serviceFrequency, "PT2M", @@ -24,21 +25,25 @@ class TestService extends Test\AbstractTest { "5M", "interval", ]; - foreach($in as $index => $spec) { - try{$exp = new \DateInterval($spec);} catch(\Exception $e) {$exp = new \DateInterval("PT2M");} + foreach ($in as $index => $spec) { + try { + $exp = new \DateInterval($spec); + } catch (\Exception $e) { + $exp = new \DateInterval("PT2M"); + } Arsse::$conf->serviceFrequency = $spec; $this->assertEquals($exp, Service::interval(), "Interval #$index '$spec' was not correctly calculated"); } } - function testCheckIn() { + public function testCheckIn() { $now = time(); $this->srv->checkIn(); Phake::verify(Arsse::$db)->metaSet("service_last_checkin", Phake::capture($then), "datetime"); $this->assertTime($now, $then); } - function testReportHavingCheckedIn() { + public function testReportHavingCheckedIn() { // the mock's metaGet() returns null by default $this->assertFalse(Service::hasCheckedIn()); $interval = Service::interval(); @@ -48,4 +53,4 @@ class TestService extends Test\AbstractTest { $this->assertTrue(Service::hasCheckedIn()); $this->assertFalse(Service::hasCheckedIn()); } -} \ No newline at end of file +} diff --git a/tests/User/TestAuthorization.php b/tests/User/TestAuthorization.php index 69a6703..4e7bbdd 100644 --- a/tests/User/TestAuthorization.php +++ b/tests/User/TestAuthorization.php @@ -1,6 +1,7 @@ clearData(); $conf = new Conf(); $conf->userDriver = $drv; $conf->userPreAuth = false; Arsse::$conf = $conf; - if($db !== null) { + if ($db !== null) { Arsse::$db = new $db(); } Arsse::$user = Phake::partialMock(User::class); Phake::when(Arsse::$user)->authorize->thenReturn(true); - foreach(self::USERS as $user => $level) { + foreach (self::USERS as $user => $level) { Arsse::$user->add($user, ""); Arsse::$user->rightsSet($user, $level); } Phake::reset(Arsse::$user); } - function tearDown() { + public function tearDown() { $this->clearData(); } - function testToggleLogic() { + public function testToggleLogic() { $this->assertTrue(Arsse::$user->authorizationEnabled()); $this->assertTrue(Arsse::$user->authorizationEnabled(true)); $this->assertFalse(Arsse::$user->authorizationEnabled(false)); @@ -75,8 +76,8 @@ class TestAuthorization extends Test\AbstractTest { $this->assertTrue(Arsse::$user->authorizationEnabled(true)); } - function testSelfActionLogic() { - foreach(array_keys(self::USERS) as $user) { + public function testSelfActionLogic() { + foreach (array_keys(self::USERS) as $user) { Arsse::$user->auth($user, ""); // users should be able to do basic actions for themselves $this->assertTrue(Arsse::$user->authorize($user, "userExists"), "User $user could not act for themselves."); @@ -84,15 +85,15 @@ class TestAuthorization extends Test\AbstractTest { } } - function testRegularUserLogic() { - foreach(self::USERS as $actor => $rights) { - if($rights != User\Driver::RIGHTS_NONE) { + public function testRegularUserLogic() { + foreach (self::USERS as $actor => $rights) { + if ($rights != User\Driver::RIGHTS_NONE) { continue; } Arsse::$user->auth($actor, ""); - foreach(array_keys(self::USERS) as $affected) { + foreach (array_keys(self::USERS) as $affected) { // regular users should only be able to act for themselves - if($actor==$affected) { + if ($actor==$affected) { $this->assertTrue(Arsse::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied."); $this->assertTrue(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied."); } else { @@ -100,41 +101,41 @@ class TestAuthorization extends Test\AbstractTest { $this->assertFalse(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed."); } // they should never be able to set rights - foreach(self::LEVELS as $level) { + foreach (self::LEVELS as $level) { $this->assertFalse(Arsse::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed."); } } // they should not be able to list users - foreach(self::DOMAINS as $domain) { + foreach (self::DOMAINS as $domain) { $this->assertFalse(Arsse::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed."); } } } - function testDomainManagerLogic() { - foreach(self::USERS as $actor => $actorRights) { - if($actorRights != User\Driver::RIGHTS_DOMAIN_MANAGER) { + public function testDomainManagerLogic() { + foreach (self::USERS as $actor => $actorRights) { + if ($actorRights != User\Driver::RIGHTS_DOMAIN_MANAGER) { continue; } - $actorDomain = substr($actor,strrpos($actor,"@")+1); + $actorDomain = substr($actor, strrpos($actor, "@")+1); Arsse::$user->auth($actor, ""); - foreach(self::USERS as $affected => $affectedRights) { - $affectedDomain = substr($affected,strrpos($affected,"@")+1); + foreach (self::USERS as $affected => $affectedRights) { + $affectedDomain = substr($affected, strrpos($affected, "@")+1); // domain managers should be able to check any user on the same domain - if($actorDomain==$affectedDomain) { + if ($actorDomain==$affectedDomain) { $this->assertTrue(Arsse::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed."); } // they should only be able to act for regular users on the same domain - if($actor==$affected || ($actorDomain==$affectedDomain && $affectedRights==User\Driver::RIGHTS_NONE)) { + if ($actor==$affected || ($actorDomain==$affectedDomain && $affectedRights==User\Driver::RIGHTS_NONE)) { $this->assertTrue(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed."); } // and they should only be able to set their own rights to regular user - foreach(self::LEVELS as $level) { - if($actor==$affected && in_array($level, [User\Driver::RIGHTS_NONE, User\Driver::RIGHTS_DOMAIN_MANAGER])) { + foreach (self::LEVELS as $level) { + if ($actor==$affected && in_array($level, [User\Driver::RIGHTS_NONE, User\Driver::RIGHTS_DOMAIN_MANAGER])) { $this->assertTrue(Arsse::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed."); @@ -142,8 +143,8 @@ class TestAuthorization extends Test\AbstractTest { } } // they should also be able to list all users on their own domain - foreach(self::DOMAINS as $domain) { - if($domain=="@".$actorDomain) { + foreach (self::DOMAINS as $domain) { + if ($domain=="@".$actorDomain) { $this->assertTrue(Arsse::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed."); @@ -152,31 +153,31 @@ class TestAuthorization extends Test\AbstractTest { } } - function testDomainAdministratorLogic() { - foreach(self::USERS as $actor => $actorRights) { - if($actorRights != User\Driver::RIGHTS_DOMAIN_ADMIN) { + public function testDomainAdministratorLogic() { + foreach (self::USERS as $actor => $actorRights) { + if ($actorRights != User\Driver::RIGHTS_DOMAIN_ADMIN) { continue; } - $actorDomain = substr($actor,strrpos($actor,"@")+1); + $actorDomain = substr($actor, strrpos($actor, "@")+1); Arsse::$user->auth($actor, ""); $allowed = [User\Driver::RIGHTS_NONE,User\Driver::RIGHTS_DOMAIN_MANAGER,User\Driver::RIGHTS_DOMAIN_ADMIN]; - foreach(self::USERS as $affected => $affectedRights) { - $affectedDomain = substr($affected,strrpos($affected,"@")+1); + foreach (self::USERS as $affected => $affectedRights) { + $affectedDomain = substr($affected, strrpos($affected, "@")+1); // domain admins should be able to check any user on the same domain - if($actorDomain==$affectedDomain) { + if ($actorDomain==$affectedDomain) { $this->assertTrue(Arsse::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed."); } // they should be able to act for any user on the same domain who is not a global manager or admin - if($actorDomain==$affectedDomain && in_array($affectedRights, $allowed)) { + if ($actorDomain==$affectedDomain && in_array($affectedRights, $allowed)) { $this->assertTrue(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed."); } // they should be able to set rights for any user on their domain who is not a global manager or admin, up to domain admin level - foreach(self::LEVELS as $level) { - if($actorDomain==$affectedDomain && in_array($affectedRights, $allowed) && in_array($level, $allowed)) { + foreach (self::LEVELS as $level) { + if ($actorDomain==$affectedDomain && in_array($affectedRights, $allowed) && in_array($level, $allowed)) { $this->assertTrue(Arsse::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed."); @@ -184,8 +185,8 @@ class TestAuthorization extends Test\AbstractTest { } } // they should also be able to list all users on their own domain - foreach(self::DOMAINS as $domain) { - if($domain=="@".$actorDomain) { + foreach (self::DOMAINS as $domain) { + if ($domain=="@".$actorDomain) { $this->assertTrue(Arsse::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed."); @@ -194,26 +195,26 @@ class TestAuthorization extends Test\AbstractTest { } } - function testGlobalManagerLogic() { - foreach(self::USERS as $actor => $actorRights) { - if($actorRights != User\Driver::RIGHTS_GLOBAL_MANAGER) { + public function testGlobalManagerLogic() { + foreach (self::USERS as $actor => $actorRights) { + if ($actorRights != User\Driver::RIGHTS_GLOBAL_MANAGER) { continue; } - $actorDomain = substr($actor,strrpos($actor,"@")+1); + $actorDomain = substr($actor, strrpos($actor, "@")+1); Arsse::$user->auth($actor, ""); - foreach(self::USERS as $affected => $affectedRights) { - $affectedDomain = substr($affected,strrpos($affected,"@")+1); + foreach (self::USERS as $affected => $affectedRights) { + $affectedDomain = substr($affected, strrpos($affected, "@")+1); // global managers should be able to check any user $this->assertTrue(Arsse::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied."); // they should only be able to act for regular users - if($actor==$affected || $affectedRights==User\Driver::RIGHTS_NONE) { + if ($actor==$affected || $affectedRights==User\Driver::RIGHTS_NONE) { $this->assertTrue(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed."); } // and they should only be able to set their own rights to regular user - foreach(self::LEVELS as $level) { - if($actor==$affected && in_array($level, [User\Driver::RIGHTS_NONE, User\Driver::RIGHTS_GLOBAL_MANAGER])) { + foreach (self::LEVELS as $level) { + if ($actor==$affected && in_array($level, [User\Driver::RIGHTS_NONE, User\Driver::RIGHTS_GLOBAL_MANAGER])) { $this->assertTrue(Arsse::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied."); } else { $this->assertFalse(Arsse::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed."); @@ -221,41 +222,41 @@ class TestAuthorization extends Test\AbstractTest { } } // they should also be able to list all users - foreach(self::DOMAINS as $domain) { + foreach (self::DOMAINS as $domain) { $this->assertTrue(Arsse::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied."); } } } - function testGlobalAdministratorLogic() { - foreach(self::USERS as $actor => $actorRights) { - if($actorRights != User\Driver::RIGHTS_GLOBAL_ADMIN) { + public function testGlobalAdministratorLogic() { + foreach (self::USERS as $actor => $actorRights) { + if ($actorRights != User\Driver::RIGHTS_GLOBAL_ADMIN) { continue; } Arsse::$user->auth($actor, ""); // global admins can do anything - foreach(self::USERS as $affected => $affectedRights) { + foreach (self::USERS as $affected => $affectedRights) { $this->assertTrue(Arsse::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied."); $this->assertTrue(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied."); - foreach(self::LEVELS as $level) { + foreach (self::LEVELS as $level) { $this->assertTrue(Arsse::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied."); } } - foreach(self::DOMAINS as $domain) { + foreach (self::DOMAINS as $domain) { $this->assertTrue(Arsse::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied."); } } } - function testInvalidLevelLogic() { - foreach(self::USERS as $actor => $rights) { - if(in_array($rights, self::LEVELS)) { + public function testInvalidLevelLogic() { + foreach (self::USERS as $actor => $rights) { + if (in_array($rights, self::LEVELS)) { continue; } Arsse::$user->auth($actor, ""); - foreach(array_keys(self::USERS) as $affected) { + foreach (array_keys(self::USERS) as $affected) { // users with unknown/invalid rights should be treated just like regular users and only be able to act for themselves - if($actor==$affected) { + if ($actor==$affected) { $this->assertTrue(Arsse::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied."); $this->assertTrue(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied."); } else { @@ -263,18 +264,18 @@ class TestAuthorization extends Test\AbstractTest { $this->assertFalse(Arsse::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed."); } // they should never be able to set rights - foreach(self::LEVELS as $level) { + foreach (self::LEVELS as $level) { $this->assertFalse(Arsse::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed."); } } // they should not be able to list users - foreach(self::DOMAINS as $domain) { + foreach (self::DOMAINS as $domain) { $this->assertFalse(Arsse::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed."); } } } - function testInternalExceptionLogic() { + public function testInternalExceptionLogic() { $tests = [ // methods of User class to test, with parameters besides affected user 'exists' => [], @@ -295,7 +296,7 @@ class TestAuthorization extends Test\AbstractTest { $this->assertCount(sizeof($tests), $this->checkExceptions("user@example.org", $tests)); } - function testExternalExceptionLogic() { + public function testExternalExceptionLogic() { // set up the test for an external driver $this->setUp(Test\User\DriverExternalMock::class, Test\User\Database::class); // run the previous test with the external driver set up @@ -306,24 +307,24 @@ class TestAuthorization extends Test\AbstractTest { // calls each requested function with supplied arguments, catches authorization exceptions, and returns an array of caught failed calls protected function checkExceptions(string $user, $tests): array { $err = []; - foreach($tests as $func => $args) { + foreach ($tests as $func => $args) { // list method does not take an affected user, so do not unshift for that one - if($func != "list") { + if ($func != "list") { array_unshift($args, $user); } try { call_user_func_array(array(Arsse::$user, $func), $args); - } catch(User\ExceptionAuthz $e) { + } catch (User\ExceptionAuthz $e) { $err[] = $func; } } return $err; } - function testMissingUserLogic() { + public function testMissingUserLogic() { Arsse::$user->auth("gadm@example.com", ""); $this->assertTrue(Arsse::$user->authorize("user@example.com", "someFunction")); $this->assertException("doesNotExist", "User"); Arsse::$user->authorize("this_user_does_not_exist@example.org", "someFunction"); } -} \ No newline at end of file +} diff --git a/tests/User/TestUserInternalDriver.php b/tests/User/TestUserInternalDriver.php index e29204c..82a707c 100644 --- a/tests/User/TestUserInternalDriver.php +++ b/tests/User/TestUserInternalDriver.php @@ -2,7 +2,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse; -/** +/** * @covers \JKingWeb\Arsse\User * @covers \JKingWeb\Arsse\User\Internal\Driver * @covers \JKingWeb\Arsse\User\Internal\InternalFunctions */ diff --git a/tests/User/TestUserMockExternal.php b/tests/User/TestUserMockExternal.php index d354ef7..5566131 100644 --- a/tests/User/TestUserMockExternal.php +++ b/tests/User/TestUserMockExternal.php @@ -10,4 +10,4 @@ class TestUserMockExternal extends Test\AbstractTest { const USER2 = "jane.doe@example.com"; public $drv = Test\User\DriverExternalMock::class; -} \ No newline at end of file +} diff --git a/tests/User/TestUserMockInternal.php b/tests/User/TestUserMockInternal.php index 5454a6c..7d931fd 100644 --- a/tests/User/TestUserMockInternal.php +++ b/tests/User/TestUserMockInternal.php @@ -11,7 +11,7 @@ class TestUserMockInternal extends Test\AbstractTest { public $drv = Test\User\DriverInternalMock::class; - function setUpSeries() { + public function setUpSeries() { Arsse::$db = null; } } diff --git a/tests/docroot/Feed/Caching/200Future.php b/tests/docroot/Feed/Caching/200Future.php index 37c85a1..ef2ae71 100644 --- a/tests/docroot/Feed/Caching/200Future.php +++ b/tests/docroot/Feed/Caching/200Future.php @@ -11,4 +11,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Caching/200Multiple.php b/tests/docroot/Feed/Caching/200Multiple.php index 0594401..583b663 100644 --- a/tests/docroot/Feed/Caching/200Multiple.php +++ b/tests/docroot/Feed/Caching/200Multiple.php @@ -27,4 +27,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Caching/200None.php b/tests/docroot/Feed/Caching/200None.php index 513cb66..562554c 100644 --- a/tests/docroot/Feed/Caching/200None.php +++ b/tests/docroot/Feed/Caching/200None.php @@ -21,4 +21,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Caching/200Past.php b/tests/docroot/Feed/Caching/200Past.php index 7d69cf5..361d767 100644 --- a/tests/docroot/Feed/Caching/200Past.php +++ b/tests/docroot/Feed/Caching/200Past.php @@ -11,4 +11,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Caching/200PubDateOnly.php b/tests/docroot/Feed/Caching/200PubDateOnly.php index fdd39e0..5b8df9b 100644 --- a/tests/docroot/Feed/Caching/200PubDateOnly.php +++ b/tests/docroot/Feed/Caching/200PubDateOnly.php @@ -16,4 +16,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Caching/200UpdateDate.php b/tests/docroot/Feed/Caching/200UpdateDate.php index 2128d2c..e7f9a20 100644 --- a/tests/docroot/Feed/Caching/200UpdateDate.php +++ b/tests/docroot/Feed/Caching/200UpdateDate.php @@ -17,4 +17,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Caching/304ETagOnly.php b/tests/docroot/Feed/Caching/304ETagOnly.php index 2b482dd..3572d57 100644 --- a/tests/docroot/Feed/Caching/304ETagOnly.php +++ b/tests/docroot/Feed/Caching/304ETagOnly.php @@ -4,4 +4,4 @@ 'fields' => [ "ETag: ".$_SERVER['HTTP_IF_NONE_MATCH'], ], -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Caching/304LastModOnly.php b/tests/docroot/Feed/Caching/304LastModOnly.php index 444ccdb..34838dc 100644 --- a/tests/docroot/Feed/Caching/304LastModOnly.php +++ b/tests/docroot/Feed/Caching/304LastModOnly.php @@ -4,4 +4,4 @@ 'fields' => [ 'Last-Modified: '.$_SERVER['HTTP_IF_MODIFIED_SINCE'], ], -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Caching/304None.php b/tests/docroot/Feed/Caching/304None.php index f8dcef0..ae0abe4 100644 --- a/tests/docroot/Feed/Caching/304None.php +++ b/tests/docroot/Feed/Caching/304None.php @@ -1,4 +1,4 @@ 304, 'cache' => false, -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Caching/304Random.php b/tests/docroot/Feed/Caching/304Random.php index c01917e..f444eb8 100644 --- a/tests/docroot/Feed/Caching/304Random.php +++ b/tests/docroot/Feed/Caching/304Random.php @@ -1,7 +1,7 @@ 304, - 'lastMod' => random_int(0,2^31), + 'lastMod' => random_int(0, 2^31), 'fields' => [ "ETag: ".bin2hex(random_bytes(8)), ], -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Deduplication/Hashes-Dates1.php b/tests/docroot/Feed/Deduplication/Hashes-Dates1.php index 364133c..4709e80 100644 --- a/tests/docroot/Feed/Deduplication/Hashes-Dates1.php +++ b/tests/docroot/Feed/Deduplication/Hashes-Dates1.php @@ -38,4 +38,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Deduplication/Hashes-Dates2.php b/tests/docroot/Feed/Deduplication/Hashes-Dates2.php index 3f2f2a2..321d675 100644 --- a/tests/docroot/Feed/Deduplication/Hashes-Dates2.php +++ b/tests/docroot/Feed/Deduplication/Hashes-Dates2.php @@ -38,4 +38,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Deduplication/Hashes-Dates3.php b/tests/docroot/Feed/Deduplication/Hashes-Dates3.php index 5eec075..01d0916 100644 --- a/tests/docroot/Feed/Deduplication/Hashes-Dates3.php +++ b/tests/docroot/Feed/Deduplication/Hashes-Dates3.php @@ -38,4 +38,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Deduplication/Hashes.php b/tests/docroot/Feed/Deduplication/Hashes.php index f0dbb11..bc6eaec 100644 --- a/tests/docroot/Feed/Deduplication/Hashes.php +++ b/tests/docroot/Feed/Deduplication/Hashes.php @@ -30,4 +30,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Deduplication/ID-Dates.php b/tests/docroot/Feed/Deduplication/ID-Dates.php index 98837ea..f26cfc5 100644 --- a/tests/docroot/Feed/Deduplication/ID-Dates.php +++ b/tests/docroot/Feed/Deduplication/ID-Dates.php @@ -34,4 +34,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Deduplication/IdenticalHashes.php b/tests/docroot/Feed/Deduplication/IdenticalHashes.php index ced4fbd..138b7b4 100644 --- a/tests/docroot/Feed/Deduplication/IdenticalHashes.php +++ b/tests/docroot/Feed/Deduplication/IdenticalHashes.php @@ -34,4 +34,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Deduplication/Permalink-Dates.php b/tests/docroot/Feed/Deduplication/Permalink-Dates.php index 51cc69d..304211a 100644 --- a/tests/docroot/Feed/Deduplication/Permalink-Dates.php +++ b/tests/docroot/Feed/Deduplication/Permalink-Dates.php @@ -34,4 +34,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Fetching/EndlessLoop.php b/tests/docroot/Feed/Fetching/EndlessLoop.php index 4b41a13..e13f504 100644 --- a/tests/docroot/Feed/Fetching/EndlessLoop.php +++ b/tests/docroot/Feed/Fetching/EndlessLoop.php @@ -4,4 +4,4 @@ 'fields' => [ 'Location: http://localhost:'.$_SERVER['SERVER_PORT'].$_SERVER['REQUEST_URI']."0", ] -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Fetching/Error.php b/tests/docroot/Feed/Fetching/Error.php index 339b57d..e99afe2 100644 --- a/tests/docroot/Feed/Fetching/Error.php +++ b/tests/docroot/Feed/Fetching/Error.php @@ -1,4 +1,4 @@ (int) $_GET['code'], 'cache' => false, -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Fetching/Timeout.php b/tests/docroot/Feed/Fetching/Timeout.php index cb0869a..f841011 100644 --- a/tests/docroot/Feed/Fetching/Timeout.php +++ b/tests/docroot/Feed/Fetching/Timeout.php @@ -3,4 +3,4 @@ sleep(5); return [ 'code' => 404, 'cache' => false, -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Fetching/TooLarge.php b/tests/docroot/Feed/Fetching/TooLarge.php index 3784c44..ce20059 100644 --- a/tests/docroot/Feed/Fetching/TooLarge.php +++ b/tests/docroot/Feed/Fetching/TooLarge.php @@ -2,7 +2,7 @@ $item = ' '.str_repeat("0", 1024).' - '; + '; return [ 'mime' => "application/rss+xml", 'content' => << MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Matching/1.php b/tests/docroot/Feed/Matching/1.php index eb04a3d..fdc2d67 100644 --- a/tests/docroot/Feed/Matching/1.php +++ b/tests/docroot/Feed/Matching/1.php @@ -48,4 +48,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Matching/2.php b/tests/docroot/Feed/Matching/2.php index 0b0102e..b5e2d51 100644 --- a/tests/docroot/Feed/Matching/2.php +++ b/tests/docroot/Feed/Matching/2.php @@ -56,4 +56,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Matching/3.php b/tests/docroot/Feed/Matching/3.php index 1daca60..d2c8c0d 100644 --- a/tests/docroot/Feed/Matching/3.php +++ b/tests/docroot/Feed/Matching/3.php @@ -56,4 +56,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Matching/4.php b/tests/docroot/Feed/Matching/4.php index 1815ea4..a68c0e0 100644 --- a/tests/docroot/Feed/Matching/4.php +++ b/tests/docroot/Feed/Matching/4.php @@ -55,4 +55,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Matching/5.php b/tests/docroot/Feed/Matching/5.php index 5cdb16c..efb5a9b 100644 --- a/tests/docroot/Feed/Matching/5.php +++ b/tests/docroot/Feed/Matching/5.php @@ -48,4 +48,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/NextFetch/1h.php b/tests/docroot/Feed/NextFetch/1h.php index ad8bfe7..dd01650 100644 --- a/tests/docroot/Feed/NextFetch/1h.php +++ b/tests/docroot/Feed/NextFetch/1h.php @@ -26,4 +26,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/NextFetch/3-36h.php b/tests/docroot/Feed/NextFetch/3-36h.php index 9ae4bb9..41d799f 100644 --- a/tests/docroot/Feed/NextFetch/3-36h.php +++ b/tests/docroot/Feed/NextFetch/3-36h.php @@ -26,4 +26,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/NextFetch/30m.php b/tests/docroot/Feed/NextFetch/30m.php index 35b42d7..a7dce24 100644 --- a/tests/docroot/Feed/NextFetch/30m.php +++ b/tests/docroot/Feed/NextFetch/30m.php @@ -26,4 +26,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/NextFetch/36h.php b/tests/docroot/Feed/NextFetch/36h.php index 85e505d..359ed9e 100644 --- a/tests/docroot/Feed/NextFetch/36h.php +++ b/tests/docroot/Feed/NextFetch/36h.php @@ -26,4 +26,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/NextFetch/3h.php b/tests/docroot/Feed/NextFetch/3h.php index 9ed4358..e2f5758 100644 --- a/tests/docroot/Feed/NextFetch/3h.php +++ b/tests/docroot/Feed/NextFetch/3h.php @@ -26,4 +26,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/NextFetch/Fallback.php b/tests/docroot/Feed/NextFetch/Fallback.php index 11cc30b..04cc8ac 100644 --- a/tests/docroot/Feed/NextFetch/Fallback.php +++ b/tests/docroot/Feed/NextFetch/Fallback.php @@ -26,4 +26,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/NextFetch/NotModified.php b/tests/docroot/Feed/NextFetch/NotModified.php index 71dcb84..6ed847a 100644 --- a/tests/docroot/Feed/NextFetch/NotModified.php +++ b/tests/docroot/Feed/NextFetch/NotModified.php @@ -1,5 +1,5 @@ 304, 'lastMod' => (int) $_GET['t'], @@ -9,4 +9,4 @@ if(array_key_exists("t", $_GET)) { 'code' => 304, 'cache' => false, ]; -} \ No newline at end of file +} diff --git a/tests/docroot/Feed/Parsing/Malformed.php b/tests/docroot/Feed/Parsing/Malformed.php index f889295..2e8d4bb 100644 --- a/tests/docroot/Feed/Parsing/Malformed.php +++ b/tests/docroot/Feed/Parsing/Malformed.php @@ -3,4 +3,4 @@ 'content' => << MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Parsing/Unsupported.php b/tests/docroot/Feed/Parsing/Unsupported.php index 647f18e..25b557f 100644 --- a/tests/docroot/Feed/Parsing/Unsupported.php +++ b/tests/docroot/Feed/Parsing/Unsupported.php @@ -3,4 +3,4 @@ 'content' => << MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Parsing/Valid.php b/tests/docroot/Feed/Parsing/Valid.php index ca376cc..f56bd66 100644 --- a/tests/docroot/Feed/Parsing/Valid.php +++ b/tests/docroot/Feed/Parsing/Valid.php @@ -38,4 +38,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Parsing/XEEAttack.php b/tests/docroot/Feed/Parsing/XEEAttack.php index 522f35a..12c4cbf 100644 --- a/tests/docroot/Feed/Parsing/XEEAttack.php +++ b/tests/docroot/Feed/Parsing/XEEAttack.php @@ -44,4 +44,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Parsing/XXEAttack.php b/tests/docroot/Feed/Parsing/XXEAttack.php index 9e21a43..dbe3866 100644 --- a/tests/docroot/Feed/Parsing/XXEAttack.php +++ b/tests/docroot/Feed/Parsing/XXEAttack.php @@ -35,4 +35,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Scraping/Document.php b/tests/docroot/Feed/Scraping/Document.php index 72205da..4ca1106 100644 --- a/tests/docroot/Feed/Scraping/Document.php +++ b/tests/docroot/Feed/Scraping/Document.php @@ -10,4 +10,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/Feed/Scraping/Feed.php b/tests/docroot/Feed/Scraping/Feed.php index 8018b52..71bf40e 100644 --- a/tests/docroot/Feed/Scraping/Feed.php +++ b/tests/docroot/Feed/Scraping/Feed.php @@ -15,4 +15,4 @@ MESSAGE_BODY -]; \ No newline at end of file +]; diff --git a/tests/docroot/IsUp.php b/tests/docroot/IsUp.php index 83fbe21..e2e69a7 100644 --- a/tests/docroot/IsUp.php +++ b/tests/docroot/IsUp.php @@ -1,4 +1,4 @@ 200, 'content' => "I'm up!", -]; \ No newline at end of file +]; diff --git a/tests/lib/AbstractTest.php b/tests/lib/AbstractTest.php index 15e29e2..391ae7a 100644 --- a/tests/lib/AbstractTest.php +++ b/tests/lib/AbstractTest.php @@ -1,18 +1,18 @@ assertSame($exp, $test); } - function clearData(bool $loadLang = true): bool { + public function clearData(bool $loadLang = true): bool { $r = new \ReflectionClass(\JKingWeb\Arsse\Arsse::class); $props = array_keys($r->getStaticProperties()); - foreach($props as $prop) { + foreach ($props as $prop) { Arsse::$$prop = null; } - if($loadLang) { + if ($loadLang) { Arsse::$lang = new \JKingWeb\Arsse\Lang(); } return true; } -} \ No newline at end of file +} diff --git a/tests/lib/Database.php b/tests/lib/Database.php index 432aa04..34d6841 100644 --- a/tests/lib/Database.php +++ b/tests/lib/Database.php @@ -6,4 +6,4 @@ class Database extends \JKingWeb\Arsse\Database { public function __construct(\JKingWeb\Arsse\Db\Driver $drv) { $this->db = $drv; } -} \ No newline at end of file +} diff --git a/tests/lib/Database/DriverSQLite3.php b/tests/lib/Database/DriverSQLite3.php index 128fccf..a898a08 100644 --- a/tests/lib/Database/DriverSQLite3.php +++ b/tests/lib/Database/DriverSQLite3.php @@ -1,19 +1,20 @@ markTestSkipped("SQLite extension not loaded"); } Arsse::$conf->dbSQLite3File = ":memory:"; $this->drv = new Driver(true); } - function nextID(string $table): int { + public function nextID(string $table): int { return $this->drv->query("SELECT (case when max(id) then max(id) else 0 end)+1 from $table")->getValue(); } -} \ No newline at end of file +} diff --git a/tests/lib/Database/SeriesArticle.php b/tests/lib/Database/SeriesArticle.php index 7a566de..0487661 100644 --- a/tests/lib/Database/SeriesArticle.php +++ b/tests/lib/Database/SeriesArticle.php @@ -1,6 +1,7 @@ checkTables = ['arsse_marks' => ["subscription","article","read","starred","modified"],]; $this->user = "john.doe@example.net"; } @@ -311,7 +312,7 @@ trait SeriesArticle { $this->assertEquals($exp, $ids); } - function testListArticlesCheckingContext() { + public function testListArticlesCheckingContext() { $this->user = "john.doe@example.com"; // get all items for user $exp = [1,2,3,4,5,6,7,8,19,20]; @@ -356,28 +357,28 @@ trait SeriesArticle { $this->compareIds([7,6], (new Context)->reverse(true)->limit(2)->latestEdition(8-1)); } - function testListArticlesOfAMissingFolder() { + public function testListArticlesOfAMissingFolder() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->articleList($this->user, (new Context)->folder(1)); } - function testListArticlesOfAMissingSubscription() { + public function testListArticlesOfAMissingSubscription() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->articleList($this->user, (new Context)->subscription(1)); } - function testListArticlesCheckingProperties() { + public function testListArticlesCheckingProperties() { $this->user = "john.doe@example.org"; $this->assertResult($this->matches, Arsse::$db->articleList($this->user)); } - function testListArticlesWithoutAuthority() { + public function testListArticlesWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->articleList($this->user); } - function testMarkAllArticlesUnread() { + public function testMarkAllArticlesUnread() { Arsse::$db->articleMark($this->user, ['read'=>false]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -388,7 +389,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAllArticlesRead() { + public function testMarkAllArticlesRead() { Arsse::$db->articleMark($this->user, ['read'=>true]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -403,7 +404,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAllArticlesUnstarred() { + public function testMarkAllArticlesUnstarred() { Arsse::$db->articleMark($this->user, ['starred'=>false]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -414,7 +415,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAllArticlesStarred() { + public function testMarkAllArticlesStarred() { Arsse::$db->articleMark($this->user, ['starred'=>true]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -429,7 +430,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAllArticlesUnreadAndUnstarred() { + public function testMarkAllArticlesUnreadAndUnstarred() { Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>false]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -443,7 +444,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAllArticlesReadAndStarred() { + public function testMarkAllArticlesReadAndStarred() { Arsse::$db->articleMark($this->user, ['read'=>true,'starred'=>true]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -461,7 +462,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAllArticlesUnreadAndStarred() { + public function testMarkAllArticlesUnreadAndStarred() { Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -479,7 +480,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAllArticlesReadAndUnstarred() { + public function testMarkAllArticlesReadAndUnstarred() { Arsse::$db->articleMark($this->user, ['read'=>true,'starred'=>false]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -497,7 +498,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkATreeFolder() { + public function testMarkATreeFolder() { Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(7)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -508,7 +509,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkALeafFolder() { + public function testMarkALeafFolder() { Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(8)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -517,12 +518,12 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAMissingFolder() { + public function testMarkAMissingFolder() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(42)); } - function testMarkASubscription() { + public function testMarkASubscription() { Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->subscription(13)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -531,12 +532,12 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAMissingSubscription() { + public function testMarkAMissingSubscription() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(2112)); } - function testMarkAnArticle() { + public function testMarkAnArticle() { Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->article(20)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -545,7 +546,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkMultipleArticles() { + public function testMarkMultipleArticles() { Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->articles([2,4,7,20])); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -555,7 +556,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkMultipleArticlessUnreadAndStarred() { + public function testMarkMultipleArticlessUnreadAndStarred() { Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles([2,4,7,20])); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -568,22 +569,22 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkTooFewMultipleArticles() { + public function testMarkTooFewMultipleArticles() { $this->assertException("tooShort", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles([])); } - function testMarkTooManyMultipleArticles() { + public function testMarkTooManyMultipleArticles() { $this->assertException("tooLong", "Db", "ExceptionInput"); - Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles(range(1,51))); + Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles(range(1, 51))); } - function testMarkAMissingArticle() { + public function testMarkAMissingArticle() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->article(1)); } - function testMarkAnEdition() { + public function testMarkAnEdition() { Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(1001)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -592,7 +593,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkMultipleEditions() { + public function testMarkMultipleEditions() { Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->editions([2,4,7,20])); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -602,7 +603,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkMultipleEditionsUnread() { + public function testMarkMultipleEditionsUnread() { Arsse::$db->articleMark($this->user, ['read'=>false], (new Context)->editions([2,4,7,1001])); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -613,7 +614,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkMultipleEditionsUnreadWithStale() { + public function testMarkMultipleEditionsUnreadWithStale() { Arsse::$db->articleMark($this->user, ['read'=>false], (new Context)->editions([2,4,7,20])); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -622,7 +623,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkMultipleEditionsUnreadAndStarredWithStale() { + public function testMarkMultipleEditionsUnreadAndStarredWithStale() { Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions([2,4,7,20])); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -634,23 +635,23 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkTooFewMultipleEditions() { + public function testMarkTooFewMultipleEditions() { $this->assertException("tooShort", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions([])); } - function testMarkTooManyMultipleEditions() { + public function testMarkTooManyMultipleEditions() { $this->assertException("tooLong", "Db", "ExceptionInput"); - Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions(range(1,51))); + Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions(range(1, 51))); } - function testMarkAStaleEditionUnread() { + public function testMarkAStaleEditionUnread() { Arsse::$db->articleMark($this->user, ['read'=>false], (new Context)->edition(20)); // no changes occur $state = $this->primeExpectations($this->data, $this->checkTables); $this->compareExpectations($state); } - function testMarkAStaleEditionStarred() { + public function testMarkAStaleEditionStarred() { Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(20)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -659,7 +660,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAStaleEditionUnreadAndStarred() { + public function testMarkAStaleEditionUnreadAndStarred() { Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->edition(20)); // only starred is changed $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -668,18 +669,18 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkAStaleEditionUnreadAndUnstarred() { + public function testMarkAStaleEditionUnreadAndUnstarred() { Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>false], (new Context)->edition(20)); // no changes occur $state = $this->primeExpectations($this->data, $this->checkTables); $this->compareExpectations($state); } - function testMarkAMissingEdition() { + public function testMarkAMissingEdition() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(2)); } - function testMarkByOldestEdition() { + public function testMarkByOldestEdition() { Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->oldestEdition(19)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -690,7 +691,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkByLatestEdition() { + public function testMarkByLatestEdition() { Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->latestEdition(20)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -703,7 +704,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkByLastModified() { + public function testMarkByLastModified() { Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->modifiedSince('2017-01-01T00:00:00Z')); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -714,7 +715,7 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkByNotLastModified() { + public function testMarkByNotLastModified() { Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->notModifiedSince('2000-01-01T00:00:00Z')); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); @@ -723,38 +724,38 @@ trait SeriesArticle { $this->compareExpectations($state); } - function testMarkArticlesWithoutAuthority() { + public function testMarkArticlesWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->articleMark($this->user, ['read'=>false]); } - function testCountStarredArticles() { + public function testCountStarredArticles() { $this->assertSame(2, Arsse::$db->articleStarredCount("john.doe@example.com")); $this->assertSame(2, Arsse::$db->articleStarredCount("john.doe@example.org")); $this->assertSame(2, Arsse::$db->articleStarredCount("john.doe@example.net")); $this->assertSame(0, Arsse::$db->articleStarredCount("jane.doe@example.com")); } - function testCountStarredArticlesWithoutAuthority() { + public function testCountStarredArticlesWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->articleStarredCount($this->user); } - function testFetchLatestEdition() { + public function testFetchLatestEdition() { $this->assertSame(1001, Arsse::$db->editionLatest($this->user)); $this->assertSame(4, Arsse::$db->editionLatest($this->user, (new Context)->subscription(12))); } - function testFetchLatestEditionOfMissingSubscription() { + public function testFetchLatestEditionOfMissingSubscription() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->editionLatest($this->user, (new Context)->subscription(1)); } - function testFetchLatestEditionWithoutAuthority() { + public function testFetchLatestEditionWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->editionLatest($this->user); } -} \ No newline at end of file +} diff --git a/tests/lib/Database/SeriesCleanup.php b/tests/lib/Database/SeriesCleanup.php index 1c6adf7..b85c39b 100644 --- a/tests/lib/Database/SeriesCleanup.php +++ b/tests/lib/Database/SeriesCleanup.php @@ -1,18 +1,18 @@ data = [ 'arsse_users' => [ 'columns' => [ @@ -109,7 +109,7 @@ trait SeriesCleanup { ]; } - function testCleanUpOrphanedFeeds() { + public function testCleanUpOrphanedFeeds() { Arsse::$db->feedCleanup(); $now = gmdate("Y-m-d H:i:s"); $state = $this->primeExpectations($this->data, [ @@ -121,42 +121,42 @@ trait SeriesCleanup { $this->compareExpectations($state); } - function testCleanUpOldArticlesWithStandardRetention() { + public function testCleanUpOldArticlesWithStandardRetention() { Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ 'arsse_articles' => ["id"] ]); - foreach([7,8,9] as $id) { + foreach ([7,8,9] as $id) { unset($state['arsse_articles']['rows'][$id - 1]); } $this->compareExpectations($state); } - function testCleanUpOldArticlesWithUnlimitedReadRetention() { + public function testCleanUpOldArticlesWithUnlimitedReadRetention() { Arsse::$conf->purgeArticlesRead = ""; Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ 'arsse_articles' => ["id"] ]); - foreach([7,8] as $id) { + foreach ([7,8] as $id) { unset($state['arsse_articles']['rows'][$id - 1]); } $this->compareExpectations($state); } - function testCleanUpOldArticlesWithUnlimitedUnreadRetention() { + public function testCleanUpOldArticlesWithUnlimitedUnreadRetention() { Arsse::$conf->purgeArticlesUnread = ""; Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ 'arsse_articles' => ["id"] ]); - foreach([9] as $id) { + foreach ([9] as $id) { unset($state['arsse_articles']['rows'][$id - 1]); } $this->compareExpectations($state); } - function testCleanUpOldArticlesWithUnlimitedRetention() { + public function testCleanUpOldArticlesWithUnlimitedRetention() { Arsse::$conf->purgeArticlesRead = ""; Arsse::$conf->purgeArticlesUnread = ""; Arsse::$db->articleCleanup(); @@ -165,4 +165,4 @@ trait SeriesCleanup { ]); $this->compareExpectations($state); } -} \ No newline at end of file +} diff --git a/tests/lib/Database/SeriesFeed.php b/tests/lib/Database/SeriesFeed.php index 532e00e..d2cd7ed 100644 --- a/tests/lib/Database/SeriesFeed.php +++ b/tests/lib/Database/SeriesFeed.php @@ -1,6 +1,7 @@ data = [ 'arsse_users' => [ 'columns' => [ @@ -56,7 +57,7 @@ trait SeriesFeed { ], 'rows' => [ [1,"http://localhost:8000/Feed/Matching/3","Ook",0,"",$past,$past,0], - [2,"http://localhost:8000/Feed/Matching/1","Eek",5,"There was an error last time",$past,$future,0], + [2,"http://localhost:8000/Feed/Matching/1","Eek",5,"There was an error last time",$past,$future,0], [3,"http://localhost:8000/Feed/Fetching/Error?code=404","Ack",0,"",$past,$now,0], [4,"http://localhost:8000/Feed/NextFetch/NotModified?t=".time(),"Ooook",0,"",$past,$past,0], [5,"http://localhost:8000/Feed/Parsing/Valid","Ooook",0,"",$past,$future,0], @@ -160,13 +161,13 @@ trait SeriesFeed { ]; } - function testListLatestItems() { - $this->assertResult($this->matches, Arsse::$db->feedMatchLatest(1,2)); + public function testListLatestItems() { + $this->assertResult($this->matches, Arsse::$db->feedMatchLatest(1, 2)); } - function testMatchItemsById() { + public function testMatchItemsById() { $this->assertResult($this->matches, Arsse::$db->feedMatchIds(1, ['804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41'])); - foreach($this->matches as $m) { + foreach ($this->matches as $m) { $exp = [$m]; $this->assertResult($exp, Arsse::$db->feedMatchIds(1, [], [$m['url_title_hash']])); $this->assertResult($exp, Arsse::$db->feedMatchIds(1, [], [], [$m['url_content_hash']])); @@ -175,7 +176,7 @@ trait SeriesFeed { $this->assertResult([['id' => 1]], Arsse::$db->feedMatchIds(1, ['e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda'])); // this ID appears in both feed 1 and feed 2; only one result should be returned } - function testUpdateAFeed() { + public function testUpdateAFeed() { // update a valid feed with both new and changed items Arsse::$db->feedUpdate(1); $now = gmdate("Y-m-d H:i:s"); @@ -215,17 +216,17 @@ trait SeriesFeed { $this->compareExpectations($state); } - function testUpdateAMissingFeed() { + public function testUpdateAMissingFeed() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->feedUpdate(2112); } - function testUpdateAFeedThrowingExceptions() { + public function testUpdateAFeedThrowingExceptions() { $this->assertException("invalidUrl", "Feed"); Arsse::$db->feedUpdate(3, true); } - function testUpdateAFeedWithEnclosuresAndCategories() { + public function testUpdateAFeedWithEnclosuresAndCategories() { Arsse::$db->feedUpdate(5); $state = $this->primeExpectations($this->data, [ 'arsse_enclosures' => ["url","type"], @@ -245,10 +246,10 @@ trait SeriesFeed { $this->compareExpectations($state); } - function testListStaleFeeds() { + public function testListStaleFeeds() { $this->assertSame([1,3,4], Arsse::$db->feedListStale()); Arsse::$db->feedUpdate(3); Arsse::$db->feedUpdate(4); $this->assertSame([1], Arsse::$db->feedListStale()); } -} \ No newline at end of file +} diff --git a/tests/lib/Database/SeriesFolder.php b/tests/lib/Database/SeriesFolder.php index ed99334..4fe7ea2 100644 --- a/tests/lib/Database/SeriesFolder.php +++ b/tests/lib/Database/SeriesFolder.php @@ -1,6 +1,7 @@ nextID("arsse_folders"); $this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "Entertainment"])); @@ -55,12 +56,12 @@ trait SeriesFolder { $this->compareExpectations($state); } - function testAddADuplicateRootFolder() { + public function testAddADuplicateRootFolder() { $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Politics"]); } - function testAddANestedFolder() { + public function testAddANestedFolder() { $user = "john.doe@example.com"; $folderID = $this->nextID("arsse_folders"); $this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "GNOME", 'parent' => 2])); @@ -70,38 +71,38 @@ trait SeriesFolder { $this->compareExpectations($state); } - function testAddANestedFolderToAMissingParent() { + public function testAddANestedFolderToAMissingParent() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology", 'parent' => 2112]); } - function testAddANestedFolderForTheWrongOwner() { + public function testAddANestedFolderForTheWrongOwner() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology", 'parent' => 4]); // folder ID 4 belongs to Jane } - function testAddAFolderWithAMissingName() { + public function testAddAFolderWithAMissingName() { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", []); } - function testAddAFolderWithABlankName() { + public function testAddAFolderWithABlankName() { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => ""]); } - function testAddAFolderWithAWhitespaceName() { + public function testAddAFolderWithAWhitespaceName() { $this->assertException("whitespace", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => " "]); } - function testAddAFolderWithoutAuthority() { + public function testAddAFolderWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology"]); } - function testListRootFolders() { + public function testListRootFolders() { $exp = [ ['id' => 5, 'name' => "Politics", 'parent' => null], ['id' => 1, 'name' => "Technology", 'parent' => null], @@ -118,7 +119,7 @@ trait SeriesFolder { Phake::verify(Arsse::$user)->authorize("admin@example.net", "folderList"); } - function testListFoldersRecursively() { + public function testListFoldersRecursively() { $exp = [ ['id' => 5, 'name' => "Politics", 'parent' => null], ['id' => 6, 'name' => "Politics", 'parent' => 2], @@ -139,23 +140,23 @@ trait SeriesFolder { Phake::verify(Arsse::$user)->authorize("jane.doe@example.com", "folderList"); } - function testListFoldersOfAMissingParent() { + public function testListFoldersOfAMissingParent() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderList("john.doe@example.com", 2112); } - function testListFoldersOfTheWrongOwner() { + public function testListFoldersOfTheWrongOwner() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderList("john.doe@example.com", 4); // folder ID 4 belongs to Jane } - function testListFoldersWithoutAuthority() { + public function testListFoldersWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->folderList("john.doe@example.com"); } - function testRemoveAFolder() { + public function testRemoveAFolder() { $this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 6)); Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderRemove"); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]); @@ -163,33 +164,33 @@ trait SeriesFolder { $this->compareExpectations($state); } - function testRemoveAFolderTree() { + public function testRemoveAFolderTree() { $this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 1)); Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderRemove"); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]); - foreach([0,1,2,5] as $index) { + foreach ([0,1,2,5] as $index) { unset($state['arsse_folders']['rows'][$index]); } $this->compareExpectations($state); } - function testRemoveAMissingFolder() { + public function testRemoveAMissingFolder() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderRemove("john.doe@example.com", 2112); } - function testRemoveAFolderOfTheWrongOwner() { + public function testRemoveAFolderOfTheWrongOwner() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderRemove("john.doe@example.com", 4); // folder ID 4 belongs to Jane } - function testRemoveAFolderWithoutAuthority() { + public function testRemoveAFolderWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->folderRemove("john.doe@example.com", 1); } - function testGetThePropertiesOfAFolder() { + public function testGetThePropertiesOfAFolder() { $exp = [ 'id' => 6, 'name' => "Politics", @@ -199,23 +200,23 @@ trait SeriesFolder { Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesGet"); } - function testGetThePropertiesOfAMissingFolder() { + public function testGetThePropertiesOfAMissingFolder() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesGet("john.doe@example.com", 2112); } - function testGetThePropertiesOfAFolderOfTheWrongOwner() { + public function testGetThePropertiesOfAFolderOfTheWrongOwner() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesGet("john.doe@example.com", 4); // folder ID 4 belongs to Jane } - function testGetThePropertiesOfAFolderWithoutAuthority() { + public function testGetThePropertiesOfAFolderWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->folderPropertiesGet("john.doe@example.com", 1); } - function testRenameAFolder() { + public function testRenameAFolder() { $this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => "Opinion"])); Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesSet"); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]); @@ -223,17 +224,17 @@ trait SeriesFolder { $this->compareExpectations($state); } - function testRenameAFolderToTheEmptyString() { + public function testRenameAFolderToTheEmptyString() { $this->assertException("missing", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => ""])); } - function testRenameAFolderToWhitespaceOnly() { + public function testRenameAFolderToWhitespaceOnly() { $this->assertException("whitespace", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => " "])); } - function testMoveAFolder() { + public function testMoveAFolder() { $this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => 5])); Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesSet"); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]); @@ -241,39 +242,39 @@ trait SeriesFolder { $this->compareExpectations($state); } - function testMoveAFolderToItsDescendant() { + public function testMoveAFolderToItsDescendant() { $this->assertException("circularDependence", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 3]); } - function testMoveAFolderToItself() { + public function testMoveAFolderToItself() { $this->assertException("circularDependence", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 1]); } - function testMoveAFolderToAMissingParent() { + public function testMoveAFolderToAMissingParent() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 2112]); } - function testCauseAFolderCollision() { + public function testCauseAFolderCollision() { $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => null]); } - function testSetThePropertiesOfAMissingFolder() { + public function testSetThePropertiesOfAMissingFolder() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 2112, ['parent' => null]); } - function testSetThePropertiesOfAFolderForTheWrongOwner() { + public function testSetThePropertiesOfAFolderForTheWrongOwner() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 4, ['parent' => null]); // folder ID 4 belongs to Jane } - function testSetThePropertiesOfAFolderWithoutAuthority() { + public function testSetThePropertiesOfAFolderWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => null]); } -} \ No newline at end of file +} diff --git a/tests/lib/Database/SeriesMeta.php b/tests/lib/Database/SeriesMeta.php index 632c61b..6a1e88f 100644 --- a/tests/lib/Database/SeriesMeta.php +++ b/tests/lib/Database/SeriesMeta.php @@ -1,6 +1,7 @@ data = $this->dataBare; // as far as tests are concerned the schema version is part of the expectations primed into the database @@ -27,14 +28,14 @@ trait SeriesMeta { $this->primeDatabase($this->dataBare); } - function testAddANewValue() { + public function testAddANewValue() { $this->assertTrue(Arsse::$db->metaSet("favourite", "Cygnus X-1")); $state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]); $state['arsse_meta']['rows'][] = ["favourite","Cygnus X-1"]; $this->compareExpectations($state); } - function testAddANewTypedValue() { + public function testAddANewTypedValue() { $this->assertTrue(Arsse::$db->metaSet("answer", 42, "int")); $this->assertTrue(Arsse::$db->metaSet("true", true, "bool")); $this->assertTrue(Arsse::$db->metaSet("false", false, "bool")); @@ -47,14 +48,14 @@ trait SeriesMeta { $this->compareExpectations($state); } - function testChangeAnExistingValue() { + public function testChangeAnExistingValue() { $this->assertTrue(Arsse::$db->metaSet("album", "Hemispheres")); $state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]); $state['arsse_meta']['rows'][1][1] = "Hemispheres"; $this->compareExpectations($state); } - function testRemoveAValue() { + public function testRemoveAValue() { $this->assertTrue(Arsse::$db->metaRemove("album")); $this->assertFalse(Arsse::$db->metaRemove("album")); $state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]); @@ -62,9 +63,9 @@ trait SeriesMeta { $this->compareExpectations($state); } - function testRetrieveAValue() { + public function testRetrieveAValue() { $this->assertSame("".Database::SCHEMA_VERSION, Arsse::$db->metaGet("schema_version")); $this->assertSame("A Farewell to Kings", Arsse::$db->metaGet("album")); $this->assertSame(null, Arsse::$db->metaGet("this_key_does_not_exist")); } -} \ No newline at end of file +} diff --git a/tests/lib/Database/SeriesMiscellany.php b/tests/lib/Database/SeriesMiscellany.php index eacf879..66a31b7 100644 --- a/tests/lib/Database/SeriesMiscellany.php +++ b/tests/lib/Database/SeriesMiscellany.php @@ -1,28 +1,28 @@ Arsse::$lang->msg("Driver.Db.SQLite3.Name"), ]; $this->assertArraySubset($exp, Database::driverList()); } - function testInitializeDatabase() { + public function testInitializeDatabase() { $d = new Database(); $this->assertSame(Database::SCHEMA_VERSION, $d->driverSchemaVersion()); } - function testManuallyInitializeDatabase() { + public function testManuallyInitializeDatabase() { $d = new Database(false); $this->assertSame(0, $d->driverSchemaVersion()); $this->assertTrue($d->driverSchemaUpdate()); $this->assertSame(Database::SCHEMA_VERSION, $d->driverSchemaVersion()); $this->assertFalse($d->driverSchemaUpdate()); } -} \ No newline at end of file +} diff --git a/tests/lib/Database/SeriesSubscription.php b/tests/lib/Database/SeriesSubscription.php index 39925d2..5ca9643 100644 --- a/tests/lib/Database/SeriesSubscription.php +++ b/tests/lib/Database/SeriesSubscription.php @@ -1,6 +1,7 @@ data['arsse_feeds']['rows'] = [ [1,"http://example.com/feed1", "Ook", "", "",strtotime("now")], [2,"http://example.com/feed2", "Eek", "", "",strtotime("now - 1 hour")], @@ -112,11 +113,11 @@ trait SeriesSubscription { $this->user = "john.doe@example.com"; } - function testAddASubscriptionToAnExistingFeed() { + public function testAddASubscriptionToAnExistingFeed() { $url = "http://example.com/feed1"; $subID = $this->nextID("arsse_subscriptions"); Phake::when(Arsse::$db)->feedUpdate->thenReturn(true); - $this->assertSame($subID,Arsse::$db->subscriptionAdd($this->user, $url)); + $this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url)); Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd"); Phake::verify(Arsse::$db, Phake::times(0))->feedUpdate(1, true); $state = $this->primeExpectations($this->data, [ @@ -127,12 +128,12 @@ trait SeriesSubscription { $this->compareExpectations($state); } - function testAddASubscriptionToANewFeed() { + public function testAddASubscriptionToANewFeed() { $url = "http://example.org/feed1"; $feedID = $this->nextID("arsse_feeds"); $subID = $this->nextID("arsse_subscriptions"); Phake::when(Arsse::$db)->feedUpdate->thenReturn(true); - $this->assertSame($subID,Arsse::$db->subscriptionAdd($this->user, $url)); + $this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url)); Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd"); Phake::verify(Arsse::$db)->feedUpdate($feedID, true); $state = $this->primeExpectations($this->data, [ @@ -144,13 +145,13 @@ trait SeriesSubscription { $this->compareExpectations($state); } - function testAddASubscriptionToAnInvalidFeed() { + public function testAddASubscriptionToAnInvalidFeed() { $url = "http://example.org/feed1"; $feedID = $this->nextID("arsse_feeds"); Phake::when(Arsse::$db)->feedUpdate->thenThrow(new FeedException($url, new \PicoFeed\Client\InvalidUrlException())); try { Arsse::$db->subscriptionAdd($this->user, $url); - } catch(FeedException $e) { + } catch (FeedException $e) { Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd"); Phake::verify(Arsse::$db)->feedUpdate($feedID, true); $state = $this->primeExpectations($this->data, [ @@ -163,20 +164,20 @@ trait SeriesSubscription { } } - function testAddADuplicateSubscription() { + public function testAddADuplicateSubscription() { $url = "http://example.com/feed2"; $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->subscriptionAdd($this->user, $url); } - function testAddASubscriptionWithoutAuthority() { + public function testAddASubscriptionWithoutAuthority() { $url = "http://example.com/feed1"; Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->subscriptionAdd($this->user, $url); } - function testRemoveASubscription() { + public function testRemoveASubscription() { $this->assertTrue(Arsse::$db->subscriptionRemove($this->user, 1)); Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionRemove"); $state = $this->primeExpectations($this->data, [ @@ -187,24 +188,24 @@ trait SeriesSubscription { $this->compareExpectations($state); } - function testRemoveAMissingSubscription() { + public function testRemoveAMissingSubscription() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionRemove($this->user, 2112); } - function testRemoveASubscriptionForTheWrongOwner() { + public function testRemoveASubscriptionForTheWrongOwner() { $this->user = "jane.doe@example.com"; $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionRemove($this->user, 1); } - function testRemoveASubscriptionWithoutAuthority() { + public function testRemoveASubscriptionWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->subscriptionRemove($this->user, 1); } - function testListSubscriptions() { + public function testListSubscriptions() { $exp = [ [ 'url' => "http://example.com/feed2", @@ -232,7 +233,7 @@ trait SeriesSubscription { $this->assertArraySubset($exp[1], Arsse::$db->subscriptionPropertiesGet($this->user, 3)); } - function testListSubscriptionsInAFolder() { + public function testListSubscriptionsInAFolder() { $exp = [ [ 'url' => "http://example.com/feed3", @@ -247,30 +248,30 @@ trait SeriesSubscription { $this->assertResult($exp, Arsse::$db->subscriptionList($this->user, 2)); } - function testListSubscriptionsInAMissingFolder() { + public function testListSubscriptionsInAMissingFolder() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionList($this->user, 4); } - function testListSubscriptionsWithoutAuthority() { + public function testListSubscriptionsWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->subscriptionList($this->user); } - function testGetThePropertiesOfAMissingSubscription() { + public function testGetThePropertiesOfAMissingSubscription() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesGet($this->user, 2112); } - function testGetThePropertiesOfASubscriptionWithoutAuthority() { + public function testGetThePropertiesOfASubscriptionWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->subscriptionPropertiesGet($this->user, 1); } - function testSetThePropertiesOfASubscription() { - Arsse::$db->subscriptionPropertiesSet($this->user, 1,[ + public function testSetThePropertiesOfASubscription() { + Arsse::$db->subscriptionPropertiesSet($this->user, 1, [ 'title' => "Ook Ook", 'folder' => 3, 'pinned' => false, @@ -283,49 +284,49 @@ trait SeriesSubscription { ]); $state['arsse_subscriptions']['rows'][0] = [1,"john.doe@example.com",2,"Ook Ook",3,0,0]; $this->compareExpectations($state); - Arsse::$db->subscriptionPropertiesSet($this->user, 1,[ + Arsse::$db->subscriptionPropertiesSet($this->user, 1, [ 'title' => null, ]); $state['arsse_subscriptions']['rows'][0] = [1,"john.doe@example.com",2,null,3,0,0]; $this->compareExpectations($state); } - function testMoveASubscriptionToAMissingFolder() { + public function testMoveASubscriptionToAMissingFolder() { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => 4]); } - function testMoveASubscriptionToTheRootFolder() { + public function testMoveASubscriptionToTheRootFolder() { $this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 3, ['folder' => null])); } - function testRenameASubscriptionToABlankTitle() { + public function testRenameASubscriptionToABlankTitle() { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => ""]); } - function testRenameASubscriptionToAWhitespaceTitle() { + public function testRenameASubscriptionToAWhitespaceTitle() { $this->assertException("whitespace", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => " "]); } - function testRenameASubscriptionToFalse() { + public function testRenameASubscriptionToFalse() { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => false]); } - function testRenameASubscriptionToZero() { + public function testRenameASubscriptionToZero() { $this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => 0])); } - function testSetThePropertiesOfAMissingSubscription() { + public function testSetThePropertiesOfAMissingSubscription() { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesSet($this->user, 2112, ['folder' => null]); } - function testSetThePropertiesOfASubscriptionWithoutAuthority() { + public function testSetThePropertiesOfASubscriptionWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => null]); } -} \ No newline at end of file +} diff --git a/tests/lib/Database/SeriesUser.php b/tests/lib/Database/SeriesUser.php index 59f071e..e4a72c5 100644 --- a/tests/lib/Database/SeriesUser.php +++ b/tests/lib/Database/SeriesUser.php @@ -1,6 +1,7 @@ assertTrue(Arsse::$db->userExists("jane.doe@example.com")); $this->assertFalse(Arsse::$db->userExists("jane.doe@example.org")); Phake::verify(Arsse::$user)->authorize("jane.doe@example.com", "userExists"); @@ -30,31 +31,31 @@ trait SeriesUser { $this->compareExpectations($this->data); } - function testCheckThatAUserExistsWithoutAuthority() { + public function testCheckThatAUserExistsWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userExists("jane.doe@example.com"); } - function testGetAPassword() { + public function testGetAPassword() { $hash = Arsse::$db->userPasswordGet("admin@example.net"); $this->assertSame('$2y$10$PbcG2ZR3Z8TuPzM7aHTF8.v61dtCjzjK78gdZJcp4UePE8T9jEgBW', $hash); Phake::verify(Arsse::$user)->authorize("admin@example.net", "userPasswordGet"); $this->assertTrue(password_verify("secret", $hash)); } - function testGetThePasswordOfAMissingUser() { + public function testGetThePasswordOfAMissingUser() { $this->assertException("doesNotExist", "User"); Arsse::$db->userPasswordGet("john.doe@example.org"); } - function testGetAPasswordWithoutAuthority() { + public function testGetAPasswordWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userPasswordGet("admin@example.net"); } - function testAddANewUser() { + public function testAddANewUser() { $this->assertSame("", Arsse::$db->userAdd("john.doe@example.org", "")); Phake::verify(Arsse::$user)->authorize("john.doe@example.org", "userAdd"); $state = $this->primeExpectations($this->data, ['arsse_users' => ['id','name','rights']]); @@ -66,7 +67,7 @@ trait SeriesUser { * @depends testGetAPassword * @depends testAddANewUser */ - function testAddANewUserWithARandomPassword() { + public function testAddANewUserWithARandomPassword() { $user1 = "john.doe@example.org"; $user2 = "john.doe@example.net"; $pass1 = Arsse::$db->userAdd($user1); @@ -84,18 +85,18 @@ trait SeriesUser { $this->assertTrue(password_verify($pass2, $hash2), "Failed verifying password of $user2 '$pass2' against hash '$hash2'."); } - function testAddAnExistingUser() { + public function testAddAnExistingUser() { $this->assertException("alreadyExists", "User"); Arsse::$db->userAdd("john.doe@example.com", ""); } - function testAddANewUserWithoutAuthority() { + public function testAddANewUserWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userAdd("john.doe@example.org", ""); } - function testRemoveAUser() { + public function testRemoveAUser() { $this->assertTrue(Arsse::$db->userRemove("admin@example.net")); Phake::verify(Arsse::$user)->authorize("admin@example.net", "userRemove"); $state = $this->primeExpectations($this->data, ['arsse_users' => ['id']]); @@ -103,36 +104,36 @@ trait SeriesUser { $this->compareExpectations($state); } - function testRemoveAMissingUser() { + public function testRemoveAMissingUser() { $this->assertException("doesNotExist", "User"); Arsse::$db->userRemove("john.doe@example.org"); } - function testRemoveAUserWithoutAuthority() { + public function testRemoveAUserWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userRemove("admin@example.net"); } - function testListAllUsers() { + public function testListAllUsers() { $users = ["admin@example.net", "jane.doe@example.com", "john.doe@example.com"]; $this->assertSame($users, Arsse::$db->userList()); Phake::verify(Arsse::$user)->authorize("", "userList"); } - function testListUsersOnADomain() { + public function testListUsersOnADomain() { $users = ["jane.doe@example.com", "john.doe@example.com"]; $this->assertSame($users, Arsse::$db->userList("example.com")); Phake::verify(Arsse::$user)->authorize("@example.com", "userList"); } - function testListAllUsersWithoutAuthority() { + public function testListAllUsersWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userList(); } - function testListUsersOnADomainWithoutAuthority() { + public function testListUsersOnADomainWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userList("example.com"); @@ -141,7 +142,7 @@ trait SeriesUser { /** * @depends testGetAPassword */ - function testSetAPassword() { + public function testSetAPassword() { $user = "john.doe@example.com"; $this->assertEquals("", Arsse::$db->userPasswordGet($user)); $pass = Arsse::$db->userPasswordSet($user, "secret"); @@ -150,25 +151,25 @@ trait SeriesUser { Phake::verify(Arsse::$user)->authorize($user, "userPasswordSet"); $this->assertTrue(password_verify($pass, $hash), "Failed verifying password of $user '$pass' against hash '$hash'."); } - function testSetARandomPassword() { + public function testSetARandomPassword() { $user = "john.doe@example.com"; $this->assertEquals("", Arsse::$db->userPasswordGet($user)); $pass = Arsse::$db->userPasswordSet($user); $hash = Arsse::$db->userPasswordGet($user); } - function testSetThePasswordOfAMissingUser() { + public function testSetThePasswordOfAMissingUser() { $this->assertException("doesNotExist", "User"); Arsse::$db->userPasswordSet("john.doe@example.org", "secret"); } - function testSetAPasswordWithoutAuthority() { + public function testSetAPasswordWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userPasswordSet("john.doe@example.com", "secret"); } - function testGetUserProperties() { + public function testGetUserProperties() { $exp = [ 'name' => 'Hard Lip Herbert', 'rights' => UserDriver::RIGHTS_GLOBAL_ADMIN, @@ -179,18 +180,18 @@ trait SeriesUser { $this->assertArrayNotHasKey("password", $props); } - function testGetThePropertiesOfAMissingUser() { + public function testGetThePropertiesOfAMissingUser() { $this->assertException("doesNotExist", "User"); Arsse::$db->userPropertiesGet("john.doe@example.org"); } - function testGetUserPropertiesWithoutAuthority() { + public function testGetUserPropertiesWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userPropertiesGet("john.doe@example.com"); } - function testSetUserProperties() { + public function testSetUserProperties() { $try = [ 'name' => 'James Kirk', // only this should actually change 'password' => '000destruct0', @@ -210,20 +211,20 @@ trait SeriesUser { $this->compareExpectations($state); } - function testSetThePropertiesOfAMissingUser() { + public function testSetThePropertiesOfAMissingUser() { $try = ['name' => 'John Doe']; $this->assertException("doesNotExist", "User"); Arsse::$db->userPropertiesSet("john.doe@example.org", $try); } - function testSetUserPropertiesWithoutAuthority() { + public function testSetUserPropertiesWithoutAuthority() { $try = ['name' => 'John Doe']; Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userPropertiesSet("john.doe@example.com", $try); } - function testGetUserRights() { + public function testGetUserRights() { $user1 = "john.doe@example.com"; $user2 = "admin@example.net"; $this->assertSame(UserDriver::RIGHTS_NONE, Arsse::$db->userRightsGet($user1)); @@ -232,18 +233,18 @@ trait SeriesUser { Phake::verify(Arsse::$user)->authorize($user2, "userRightsGet"); } - function testGetTheRightsOfAMissingUser() { + public function testGetTheRightsOfAMissingUser() { $this->assertSame(UserDriver::RIGHTS_NONE, Arsse::$db->userRightsGet("john.doe@example.org")); Phake::verify(Arsse::$user)->authorize("john.doe@example.org", "userRightsGet"); } - function testGetUserRightsWithoutAuthority() { + public function testGetUserRightsWithoutAuthority() { Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userRightsGet("john.doe@example.com"); } - function testSetUserRights() { + public function testSetUserRights() { $user = "john.doe@example.com"; $rights = UserDriver::RIGHTS_GLOBAL_ADMIN; $this->assertTrue(Arsse::$db->userRightsSet($user, $rights)); @@ -253,16 +254,16 @@ trait SeriesUser { $this->compareExpectations($state); } - function testSetTheRightsOfAMissingUser() { + public function testSetTheRightsOfAMissingUser() { $rights = UserDriver::RIGHTS_GLOBAL_ADMIN; $this->assertException("doesNotExist", "User"); Arsse::$db->userRightsSet("john.doe@example.org", $rights); } - function testSetUserRightsWithoutAuthority() { + public function testSetUserRightsWithoutAuthority() { $rights = UserDriver::RIGHTS_GLOBAL_ADMIN; Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); Arsse::$db->userRightsSet("john.doe@example.com", $rights); } -} \ No newline at end of file +} diff --git a/tests/lib/Database/Setup.php b/tests/lib/Database/Setup.php index 57484fc..3dfba36 100644 --- a/tests/lib/Database/Setup.php +++ b/tests/lib/Database/Setup.php @@ -1,6 +1,7 @@ clearData(); // create a default configuration @@ -27,28 +28,34 @@ trait Setup { Arsse::$user = Phake::mock(User::class); Phake::when(Arsse::$user)->authorize->thenReturn(true); // call the additional setup method if it exists - if(method_exists($this, "setUpSeries")) $this->setUpSeries(); + if (method_exists($this, "setUpSeries")) { + $this->setUpSeries(); + } // prime the database with series data if it hasn't already been done - if(!$this->primed && isset($this->data)) $this->primeDatabase($this->data); + if (!$this->primed && isset($this->data)) { + $this->primeDatabase($this->data); + } } - function tearDown() { + public function tearDown() { // call the additional teardiwn method if it exists - if(method_exists($this, "tearDownSeries")) $this->tearDownSeries(); + if (method_exists($this, "tearDownSeries")) { + $this->tearDownSeries(); + } // clean up $this->primed = false; $this->drv = null; $this->clearData(); } - function primeDatabase(array $data): bool { + public function primeDatabase(array $data): bool { $tr = $this->drv->begin(); - foreach($data as $table => $info) { + foreach ($data as $table => $info) { $cols = implode(",", array_keys($info['columns'])); $bindings = array_values($info['columns']); $params = implode(",", array_fill(0, sizeof($info['columns']), "?")); $s = $this->drv->prepareArray("INSERT INTO $table($cols) values($params)", $bindings); - foreach($info['rows'] as $row) { + foreach ($info['rows'] as $row) { $this->assertEquals(1, $s->runArray($row)->changes()); } } @@ -57,12 +64,12 @@ trait Setup { return true; } - function compareExpectations(array $expected): bool { - foreach($expected as $table => $info) { + public function compareExpectations(array $expected): bool { + foreach ($expected as $table => $info) { $cols = implode(",", array_keys($info['columns'])); $data = $this->drv->prepare("SELECT $cols from $table")->run()->getAll(); $cols = array_keys($info['columns']); - foreach($info['rows'] as $index => $row) { + foreach ($info['rows'] as $index => $row) { $this->assertCount(sizeof($cols), $row, "The number of values for array index $index does not match the number of fields"); $row = array_combine($cols, $row); $this->assertContains($row, $data, "Table $table does not contain record at array index $index."); @@ -74,14 +81,14 @@ trait Setup { return true; } - function primeExpectations(array $source, array $tableSpecs = null): array { + public function primeExpectations(array $source, array $tableSpecs = null): array { $out = []; - foreach($tableSpecs as $table => $columns) { + foreach ($tableSpecs as $table => $columns) { // make sure the source has the table we want $this->assertArrayHasKey($table, $source, "Source for expectations does not contain requested table $table."); $out[$table] = [ 'columns' => [], - 'rows' => array_fill(0,sizeof($source[$table]['rows']), []), + 'rows' => array_fill(0, sizeof($source[$table]['rows']), []), ]; // make sure the source has all the columns we want for the table $cols = array_flip($columns); @@ -89,10 +96,10 @@ trait Setup { $this->assertSame(array_keys($cols), $columns, "Source for table $table does not contain all requested columns"); // get a map of source value offsets and keys $targets = array_flip(array_keys($source[$table]['columns'])); - foreach($cols as $key => $order) { + foreach ($cols as $key => $order) { // fill the column-spec $out[$table]['columns'][$key] = $source[$table]['columns'][$key]; - foreach($source[$table]['rows'] as $index => $row) { + foreach ($source[$table]['rows'] as $index => $row) { // fill each row column-wise with re-ordered values $out[$table]['rows'][$index][$order] = $row[$targets[$key]]; } @@ -101,13 +108,13 @@ trait Setup { return $out; } - function assertResult(array $expected, Result $data) { + public function assertResult(array $expected, Result $data) { $data = $data->getAll(); $this->assertCount(sizeof($expected), $data, "Number of result rows (".sizeof($data).") differs from number of expected rows (".sizeof($expected).")"); - if(sizeof($expected)) { + if (sizeof($expected)) { // make sure the expectations are consistent - foreach($expected as $exp) { - if(!isset($keys)) { + foreach ($expected as $exp) { + if (!isset($keys)) { $keys = $exp; continue; } @@ -115,15 +122,15 @@ trait Setup { } // filter the result set to contain just the desired keys (we don't care if the result has extra keys) $rows = []; - foreach($data as $row) { + foreach ($data as $row) { $rows[] = array_intersect_key($row, $keys); } // compare the result set to the expectations - foreach($expected as $index => $exp) { + foreach ($expected as $index => $exp) { $this->assertContains($exp, $rows, "Result set does not contain record at array index $index."); $found = array_search($exp, $rows, true); unset($rows[$found]); } } } -} \ No newline at end of file +} diff --git a/tests/lib/Db/BindingTests.php b/tests/lib/Db/BindingTests.php index 6bf705a..3c0286c 100644 --- a/tests/lib/Db/BindingTests.php +++ b/tests/lib/Db/BindingTests.php @@ -1,10 +1,11 @@ null, @@ -34,7 +35,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindTrue() { + public function testBindTrue() { $input = true; $exp = [ "null" => null, @@ -51,7 +52,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindFalse() { + public function testBindFalse() { $input = false; $exp = [ "null" => null, @@ -68,7 +69,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindInteger() { + public function testBindInteger() { $input = 2112; $exp = [ "null" => null, @@ -85,7 +86,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindIntegerZero() { + public function testBindIntegerZero() { $input = 0; $exp = [ "null" => null, @@ -102,7 +103,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindFloat() { + public function testBindFloat() { $input = 2112.0; $exp = [ "null" => null, @@ -119,7 +120,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindFloatZero() { + public function testBindFloatZero() { $input = 0.0; $exp = [ "null" => null, @@ -136,7 +137,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindAsciiString() { + public function testBindAsciiString() { $input = "Random string"; $exp = [ "null" => null, @@ -153,7 +154,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindUtf8String() { + public function testBindUtf8String() { $input = "é"; $exp = [ "null" => null, @@ -170,7 +171,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindBinaryString() { + public function testBindBinaryString() { // FIXME: This test may be unreliable; SQLite happily stores invalid UTF-8 text as bytes untouched, but other engines probably don't do this $input = chr(233); $exp = [ @@ -188,7 +189,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindIso8601DateString() { + public function testBindIso8601DateString() { $input = "2017-01-09T13:11:17"; $time = strtotime($input); $exp = [ @@ -206,7 +207,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindArbitraryDateString() { + public function testBindArbitraryDateString() { $input = "Today"; $time = strtotime($input); $exp = [ @@ -224,7 +225,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindMutableDateObject($class = '\DateTime') { + public function testBindMutableDateObject($class = '\DateTime') { $input = new $class("Noon Today"); $time = $input->getTimestamp(); $exp = [ @@ -242,7 +243,7 @@ trait BindingTests { $this->checkBinding($input, $exp, true); } - function testBindImmutableDateObject() { + public function testBindImmutableDateObject() { $this->testBindMutableDateObject('\DateTimeImmutable'); } -} \ No newline at end of file +} diff --git a/tests/lib/Lang/Setup.php b/tests/lib/Lang/Setup.php index 42e68bb..2d40313 100644 --- a/tests/lib/Lang/Setup.php +++ b/tests/lib/Lang/Setup.php @@ -1,15 +1,14 @@ files = [ 'en.php' => ' "and the Philosopher\'s Stone"];', @@ -40,16 +39,20 @@ trait Setup { Arsse::$lang = Phake::mock(Lang::class); Phake::when(Arsse::$lang)->msg->thenReturn(""); // call the additional setup method if it exists - if(method_exists($this, "setUpSeries")) $this->setUpSeries(); + if (method_exists($this, "setUpSeries")) { + $this->setUpSeries(); + } } - function tearDown() { + public function tearDown() { // verify calls to the mock Lang object Phake::verify(Arsse::$lang, Phake::atLeast(0))->msg($this->isType("string"), $this->anything()); Phake::verifyNoOtherInteractions(Arsse::$lang); // clean up $this->clearData(true); // call the additional teardiwn method if it exists - if(method_exists($this, "tearDownSeries")) $this->tearDownSeries(); + if (method_exists($this, "tearDownSeries")) { + $this->tearDownSeries(); + } } -} \ No newline at end of file +} diff --git a/tests/lib/Lang/TestLang.php b/tests/lib/Lang/TestLang.php index 0d482ca..560497b 100644 --- a/tests/lib/Lang/TestLang.php +++ b/tests/lib/Lang/TestLang.php @@ -1,11 +1,11 @@ path."*.php"); } -} \ No newline at end of file +} diff --git a/tests/lib/Result.php b/tests/lib/Result.php index fb85701..3bf3316 100644 --- a/tests/lib/Result.php +++ b/tests/lib/Result.php @@ -14,7 +14,7 @@ class Result implements \JKingWeb\Arsse\Db\Result { public function getValue() { $arr = $this->next(); - if($this->valid()) { + if ($this->valid()) { $keys = array_keys($arr); return $arr[array_shift($keys)]; } @@ -70,4 +70,4 @@ class Result implements \JKingWeb\Arsse\Db\Result { public function rewind() { reset($this->set); } -} \ No newline at end of file +} diff --git a/tests/lib/User/CommonTests.php b/tests/lib/User/CommonTests.php index 5a2f62c..f1b6831 100644 --- a/tests/lib/User/CommonTests.php +++ b/tests/lib/User/CommonTests.php @@ -1,6 +1,7 @@ clearData(); $conf = new Conf(); $conf->userDriver = $this->drv; @@ -21,58 +21,62 @@ trait CommonTests { $_SERVER['PHP_AUTH_USER'] = self::USER1; $_SERVER['PHP_AUTH_PW'] = "secret"; // call the additional setup method if it exists - if(method_exists($this, "setUpSeries")) $this->setUpSeries(); + if (method_exists($this, "setUpSeries")) { + $this->setUpSeries(); + } } - function tearDown() { + public function tearDown() { $this->clearData(); // call the additional teardiwn method if it exists - if(method_exists($this, "tearDownSeries")) $this->tearDownSeries(); + if (method_exists($this, "tearDownSeries")) { + $this->tearDownSeries(); + } } - function testListUsers() { - $this->assertCount(0,Arsse::$user->list()); + public function testListUsers() { + $this->assertCount(0, Arsse::$user->list()); } - function testCheckIfAUserDoesNotExist() { + public function testCheckIfAUserDoesNotExist() { $this->assertFalse(Arsse::$user->exists(self::USER1)); } - function testAddAUser() { + public function testAddAUser() { Arsse::$user->add(self::USER1, ""); - $this->assertCount(1,Arsse::$user->list()); + $this->assertCount(1, Arsse::$user->list()); } - function testCheckIfAUserDoesExist() { + public function testCheckIfAUserDoesExist() { Arsse::$user->add(self::USER1, ""); $this->assertTrue(Arsse::$user->exists(self::USER1)); } - function testAddADuplicateUser() { + public function testAddADuplicateUser() { Arsse::$user->add(self::USER1, ""); $this->assertException("alreadyExists", "User"); Arsse::$user->add(self::USER1, ""); } - function testAddMultipleUsers() { + public function testAddMultipleUsers() { Arsse::$user->add(self::USER1, ""); Arsse::$user->add(self::USER2, ""); - $this->assertCount(2,Arsse::$user->list()); + $this->assertCount(2, Arsse::$user->list()); } - function testRemoveAUser() { + public function testRemoveAUser() { Arsse::$user->add(self::USER1, ""); - $this->assertCount(1,Arsse::$user->list()); + $this->assertCount(1, Arsse::$user->list()); Arsse::$user->remove(self::USER1); - $this->assertCount(0,Arsse::$user->list()); + $this->assertCount(0, Arsse::$user->list()); } - function testRemoveAMissingUser() { + public function testRemoveAMissingUser() { $this->assertException("doesNotExist", "User"); Arsse::$user->remove(self::USER1); } - function testAuthenticateAUser() { + public function testAuthenticateAUser() { $_SERVER['PHP_AUTH_USER'] = self::USER1; $_SERVER['PHP_AUTH_PW'] = "secret"; Arsse::$user->add(self::USER1, "secret"); @@ -83,7 +87,7 @@ trait CommonTests { $this->assertTrue(Arsse::$user->auth(self::USER2, "")); } - function testChangeAPassword() { + public function testChangeAPassword() { Arsse::$user->add(self::USER1, "secret"); $this->assertEquals("superman", Arsse::$user->passwordSet(self::USER1, "superman")); $this->assertTrue(Arsse::$user->auth(self::USER1, "superman")); @@ -93,12 +97,12 @@ trait CommonTests { $this->assertEquals(Arsse::$conf->userTempPasswordLength, strlen(Arsse::$user->passwordSet(self::USER1))); } - function testChangeAPasswordForAMissingUser() { + public function testChangeAPasswordForAMissingUser() { $this->assertException("doesNotExist", "User"); Arsse::$user->passwordSet(self::USER1, "superman"); } - function testGetThePropertiesOfAUser() { + public function testGetThePropertiesOfAUser() { Arsse::$user->add(self::USER1, "secret"); $p = Arsse::$user->propertiesGet(self::USER1); $this->assertArrayHasKey('id', $p); @@ -109,7 +113,7 @@ trait CommonTests { $this->assertEquals(self::USER1, $p['name']); } - function testSetThePropertiesOfAUser() { + public function testSetThePropertiesOfAUser() { $pSet = [ 'name' => 'John Doe', 'id' => 'invalid', @@ -131,14 +135,14 @@ trait CommonTests { $this->assertFalse(Arsse::$user->auth(self::USER1, "superman")); } - function testGetTheRightsOfAUser() { + public function testGetTheRightsOfAUser() { Arsse::$user->add(self::USER1, ""); $this->assertEquals(Driver::RIGHTS_NONE, Arsse::$user->rightsGet(self::USER1)); } - function testSetTheRightsOfAUser() { + public function testSetTheRightsOfAUser() { Arsse::$user->add(self::USER1, ""); Arsse::$user->rightsSet(self::USER1, Driver::RIGHTS_GLOBAL_ADMIN); $this->assertEquals(Driver::RIGHTS_GLOBAL_ADMIN, Arsse::$user->rightsGet(self::USER1)); } -} \ No newline at end of file +} diff --git a/tests/lib/User/Database.php b/tests/lib/User/Database.php index 322c921..aac0428 100644 --- a/tests/lib/User/Database.php +++ b/tests/lib/User/Database.php @@ -1,6 +1,7 @@ authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + public function userExists(string $user): bool { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + } return parent::userExists($user); } - function userAdd(string $user, string $password = null): string { - if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - if($this->userExists($user)) throw new Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]); - if($password===null) $password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); + public function userAdd(string $user, string $password = null): string { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + } + if ($this->userExists($user)) { + throw new Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]); + } + if ($password===null) { + $password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); + } return parent::userAdd($user, $password); } - function userRemove(string $user): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userRemove(string $user): bool { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + } + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } return parent::userRemove($user); } - function userList(string $domain = null): array { - if($domain===null) { - if(!Arsse::$user->authorize("", __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => "global"]); + public function userList(string $domain = null): array { + if ($domain===null) { + if (!Arsse::$user->authorize("", __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => "global"]); + } return parent::userList(); } else { $suffix = '@'.$domain; - if(!Arsse::$user->authorize($suffix, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $domain]); + if (!Arsse::$user->authorize($suffix, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $domain]); + } return parent::userList($domain); } } - function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string { - if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); - if($newPassword===null) $newPassword = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); + public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + } + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } + if ($newPassword===null) { + $newPassword = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); + } return parent::userPasswordSet($user, $newPassword); } - function userPropertiesGet(string $user): array { - if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userPropertiesGet(string $user): array { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + } + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } $out = parent::userPropertiesGet($user); unset($out['password']); return $out; } - function userPropertiesSet(string $user, array $properties): array { - if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userPropertiesSet(string $user, array $properties): array { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + } + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } parent::userPropertiesSet($user, $properties); return $this->userPropertiesGet($user); } - function userRightsGet(string $user): int { - if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userRightsGet(string $user): int { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + } + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } return parent::userRightsGet($user); } - function userRightsSet(string $user, int $level): bool { - if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userRightsSet(string $user, int $level): bool { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + } + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } return parent::userRightsSet($user, $level); } // specific to mock database - function userPasswordGet(string $user): string { - if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userPasswordGet(string $user): string { + if (!Arsse::$user->authorize($user, __FUNCTION__)) { + throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + } + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } return $this->db[$user]['password']; } -} \ No newline at end of file +} diff --git a/tests/lib/User/DriverExternalMock.php b/tests/lib/User/DriverExternalMock.php index f0f74ef..225ecc7 100644 --- a/tests/lib/User/DriverExternalMock.php +++ b/tests/lib/User/DriverExternalMock.php @@ -1,13 +1,13 @@ Driver::FUNC_EXTERNAL, @@ -22,13 +22,15 @@ class DriverExternalMock extends DriverSkeleton implements Driver { "userRightsSet" => Driver::FUNC_EXTERNAL, ]; - static public function driverName(): string { + public static function driverName(): string { return "Mock External Driver"; } public function driverFunctions(string $function = null) { - if($function===null) return $this->functions; - if(array_key_exists($function, $this->functions)) { + if ($function===null) { + return $this->functions; + } + if (array_key_exists($function, $this->functions)) { return $this->functions[$function]; } else { return Driver::FUNC_NOT_IMPLEMENTED; @@ -38,60 +40,84 @@ class DriverExternalMock extends DriverSkeleton implements Driver { public function __construct() { } - function auth(string $user, string $password): bool { - if(!$this->userExists($user)) return false; - if($password==="" && $this->db[$user]['password']==="") return true; - if(password_verify($password, $this->db[$user]['password'])) return true; + public function auth(string $user, string $password): bool { + if (!$this->userExists($user)) { + return false; + } + if ($password==="" && $this->db[$user]['password']==="") { + return true; + } + if (password_verify($password, $this->db[$user]['password'])) { + return true; + } return false; } - function userExists(string $user): bool { + public function userExists(string $user): bool { return parent::userExists($user); } - function userAdd(string $user, string $password = null): string { - if($this->userExists($user)) throw new Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]); - if($password===null) $password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); + public function userAdd(string $user, string $password = null): string { + if ($this->userExists($user)) { + throw new Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]); + } + if ($password===null) { + $password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); + } return parent::userAdd($user, $password); } - function userRemove(string $user): bool { - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userRemove(string $user): bool { + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } return parent::userRemove($user); } - function userList(string $domain = null): array { - if($domain===null) { + public function userList(string $domain = null): array { + if ($domain===null) { return parent::userList(); } else { return parent::userList($domain); } } - function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string { - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); - if($newPassword===null) $newPassword = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); + public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string { + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } + if ($newPassword===null) { + $newPassword = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get(); + } return parent::userPasswordSet($user, $newPassword); } - function userPropertiesGet(string $user): array { - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userPropertiesGet(string $user): array { + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } return parent::userPropertiesGet($user); } - function userPropertiesSet(string $user, array $properties): array { - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userPropertiesSet(string $user, array $properties): array { + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } parent::userPropertiesSet($user, $properties); return $this->userPropertiesGet($user); } - function userRightsGet(string $user): int { - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userRightsGet(string $user): int { + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } return parent::userRightsGet($user); } - function userRightsSet(string $user, int $level): bool { - if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + public function userRightsSet(string $user, int $level): bool { + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); + } return parent::userRightsSet($user, $level); } -} \ No newline at end of file +} diff --git a/tests/lib/User/DriverInternalMock.php b/tests/lib/User/DriverInternalMock.php index f9cec1c..e78beac 100644 --- a/tests/lib/User/DriverInternalMock.php +++ b/tests/lib/User/DriverInternalMock.php @@ -1,10 +1,10 @@ Driver::FUNC_INTERNAL, @@ -19,13 +19,15 @@ class DriverInternalMock extends Database implements Driver { "userRightsSet" => Driver::FUNC_INTERNAL, ]; - static public function driverName(): string { + public static function driverName(): string { return "Mock Internal Driver"; } public function driverFunctions(string $function = null) { - if($function===null) return $this->functions; - if(array_key_exists($function, $this->functions)) { + if ($function===null) { + return $this->functions; + } + if (array_key_exists($function, $this->functions)) { return $this->functions[$function]; } else { return Driver::FUNC_NOT_IMPLEMENTED; @@ -35,10 +37,16 @@ class DriverInternalMock extends Database implements Driver { public function __construct() { } - function auth(string $user, string $password): bool { - if(!$this->userExists($user)) return false; - if($password==="" && $this->db[$user]['password']==="") return true; - if(password_verify($password, $this->db[$user]['password'])) return true; + public function auth(string $user, string $password): bool { + if (!$this->userExists($user)) { + return false; + } + if ($password==="" && $this->db[$user]['password']==="") { + return true; + } + if (password_verify($password, $this->db[$user]['password'])) { + return true; + } return false; } -} \ No newline at end of file +} diff --git a/tests/lib/User/DriverSkeleton.php b/tests/lib/User/DriverSkeleton.php index 643a53e..b221021 100644 --- a/tests/lib/User/DriverSkeleton.php +++ b/tests/lib/User/DriverSkeleton.php @@ -1,6 +1,7 @@ db); } - function userAdd(string $user, string $password = null): string { + public function userAdd(string $user, string $password = null): string { $u = [ 'password' => $password ? password_hash($password, \PASSWORD_DEFAULT) : "", 'rights' => Driver::RIGHTS_NONE, @@ -24,45 +24,45 @@ abstract class DriverSkeleton { return $password; } - function userRemove(string $user): bool { + public function userRemove(string $user): bool { unset($this->db[$user]); return true; } - function userList(string $domain = null): array { + public function userList(string $domain = null): array { $list = array_keys($this->db); - if($domain===null) { + if ($domain===null) { return $list; } else { $suffix = '@'.$domain; $len = -1 * strlen($suffix); - return array_filter($list, function($user) use($suffix, $len) { + return array_filter($list, function ($user) use ($suffix, $len) { return substr_compare($user, $suffix, $len); }); } } - function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string { + public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string { $this->db[$user]['password'] = password_hash($newPassword, \PASSWORD_DEFAULT); return $newPassword; } - function userPropertiesGet(string $user): array { + public function userPropertiesGet(string $user): array { $out = $this->db[$user]; return $out; } - function userPropertiesSet(string $user, array $properties): array { + public function userPropertiesSet(string $user, array $properties): array { $this->db[$user] = array_merge($this->db[$user], $properties); return $this->userPropertiesGet($user); } - function userRightsGet(string $user): int { + public function userRightsGet(string $user): int { return $this->db[$user]['rights']; } - function userRightsSet(string $user, int $level): bool { + public function userRightsSet(string $user, int $level): bool { $this->db[$user]['rights'] = $level; return true; } -} \ No newline at end of file +} diff --git a/tests/server.php b/tests/server.php index bc77314..a95d396 100644 --- a/tests/server.php +++ b/tests/server.php @@ -1,6 +1,7 @@ [], ]; -$url = explode("?",$_SERVER['REQUEST_URI'])[0]; +$url = explode("?", $_SERVER['REQUEST_URI'])[0]; $base = BASE."tests".\DIRECTORY_SEPARATOR."docroot"; -$test = $base.str_replace("/",\DIRECTORY_SEPARATOR,$url).".php"; -if(!file_exists($test)) { +$test = $base.str_replace("/", \DIRECTORY_SEPARATOR, $url).".php"; +if (!file_exists($test)) { $response = [ 'code' => 499, 'content' => "Test '$test' missing.", @@ -53,15 +54,19 @@ if(!file_exists($test)) { // set the response code http_response_code((int) $response['code']); // if the response has a body, set the content type and (possibly) the ETag. -if(strlen($response['content'])) { +if (strlen($response['content'])) { header("Content-Type: ".$response['mime']); - if($response['cache']) header('ETag: "'.md5($response['content']).'"'); + if ($response['cache']) { + header('ETag: "'.md5($response['content']).'"'); + } } // if caching is enabled, set the last-modified date -if($response['cache']) header("Last-Modified: ".gmdate("D, d M Y H:i:s \G\M\T", $response['lastMod'])); +if ($response['cache']) { + header("Last-Modified: ".gmdate("D, d M Y H:i:s \G\M\T", $response['lastMod'])); +} // set any other specified fields verbatim -foreach($response['fields'] as $h) { +foreach ($response['fields'] as $h) { header($h); } // send the content -echo $response['content']; \ No newline at end of file +echo $response['content'];