diff --git a/RoboFile.php b/RoboFile.php index f4c5ea7..17456c1 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -24,7 +24,7 @@ class RoboFile extends \Robo\Tasks { * ./robo test --testsuite TTRSS --exclude-group slow --testdox * * Please see the PHPUnit documentation for available options. - */ + */ public function test(array $args): Result { return $this->runTests(escapeshellarg(\PHP_BINARY), "typical", $args); } @@ -33,7 +33,7 @@ class RoboFile extends \Robo\Tasks { * * This includes pedantic tests which may help to identify problems. * See help for the "test" task for more details. - */ + */ public function testFull(array $args): Result { return $this->runTests(escapeshellarg(\PHP_BINARY), "full", $args); } @@ -42,7 +42,7 @@ class RoboFile extends \Robo\Tasks { * Runs a quick subset of the test suite * * See help for the "test" task for more details. - */ + */ public function testQuick(array $args): Result { return $this->runTests(escapeshellarg(\PHP_BINARY), "quick", $args); } @@ -56,7 +56,7 @@ class RoboFile extends \Robo\Tasks { * Robo first tries to use pcov and will fall back first to xdebug then * phpdbg. Neither pcov nor xdebug need to be enabled to be used; they * only need to be present in the extension load path to be used. - */ + */ public function coverage(array $args): Result { // run tests with code coverage reporting enabled $exec = $this->findCoverageEngine(); @@ -71,7 +71,7 @@ class RoboFile extends \Robo\Tasks { * run all tests which may cover code. * * See also help for the "coverage" task for more details. - */ + */ public function coverageFull(array $args): Result { // run tests with code coverage reporting enabled $exec = $this->findCoverageEngine(); @@ -121,7 +121,7 @@ class RoboFile extends \Robo\Tasks { return $all ? ">$hole 2>&1" : "2>$hole"; } - protected function runTests(string $executor, string $set, array $args) : Result { + protected function runTests(string $executor, string $set, array $args): Result { switch ($set) { case "typical": $set = ["--exclude-group", "optional"]; @@ -153,7 +153,7 @@ class RoboFile extends \Robo\Tasks { * Note that while it is possible to re-package old versions, the resultant tarball * may not be equivalent due to subsequent changes in the exclude list, or because * of new tooling. - */ + */ public function package(string $version = null): Result { // establish which commit to package $version = $version ?? $this->askDefault("Commit to package:", "HEAD"); diff --git a/arsse.php b/arsse.php index 1fe1870..546723b 100644 --- a/arsse.php +++ b/arsse.php @@ -3,6 +3,7 @@ * Copyright 2017 J. King, Dustin Wilson et al. * See LICENSE and AUTHORS files for details */ +declare(strict_types=1); namespace JKingWeb\Arsse; const BASE = __DIR__.DIRECTORY_SEPARATOR; @@ -13,7 +14,6 @@ ignore_user_abort(true); ini_set("memory_limit", "-1"); ini_set("max_execution_time", "0"); - if (\PHP_SAPI === "cli") { // initialize the CLI; this automatically handles --help and --version $cli = new CLI; diff --git a/lib/CLI.php b/lib/CLI.php index 017ad46..6d08c29 100644 --- a/lib/CLI.php +++ b/lib/CLI.php @@ -271,7 +271,7 @@ USAGE_TEXT; } protected function userAuthenticate(string $user, string $password, bool $fever = false): int { - $result = $fever ? $this->getInstance(Fever::class)->authenticate($user, $password) : Arsse::$user->auth($user, $password); + $result = $fever ? $this->getInstance(Fever::class)->authenticate($user, $password) : Arsse::$user->auth($user, $password); if ($result) { echo Arsse::$lang->msg("CLI.Auth.Success").\PHP_EOL; return 0; diff --git a/lib/Conf.php b/lib/Conf.php index 13635c8..3c1beb8 100644 --- a/lib/Conf.php +++ b/lib/Conf.php @@ -15,104 +15,104 @@ use JKingWeb\Arsse\Misc\ValueInfo as Value; * All public properties are configuration parameters that may be set by the server administrator. */ class Conf { /** @var string Default language to use for logging and errors */ - public $lang = "en"; + public $lang = "en"; /** @var string The database driver to use, one of "sqlite3", "postgresql", or "mysql". A fully-qualified class name may also be used for custom drivers */ - public $dbDriver = "sqlite3"; + public $dbDriver = "sqlite3"; /** @var boolean Whether to attempt to automatically update the database when upgrading to a new version with schema changes */ - public $dbAutoUpdate = true; + public $dbAutoUpdate = true; /** @var \DateInterval|null Number of seconds to wait before returning a timeout error when connecting to a database (null waits forever; not applicable to SQLite) */ - public $dbTimeoutConnect = 5.0; + public $dbTimeoutConnect = 5.0; /** @var \DateInterval|null Number of seconds to wait before returning a timeout error when executing a database operation (null waits forever; not applicable to SQLite) */ - public $dbTimeoutExec = null; + public $dbTimeoutExec = null; /** @var \DateInterval|null Number of seconds to wait before returning a timeout error when acquiring a database lock (null waits forever) */ - public $dbTimeoutLock = 60.0; + public $dbTimeoutLock = 60.0; /** @var string|null Full path and file name of SQLite database (if using SQLite) */ - public $dbSQLite3File = null; + public $dbSQLite3File = null; /** @var string Encryption key to use for SQLite database (if using a version of SQLite with SEE) */ - public $dbSQLite3Key = ""; + public $dbSQLite3Key = ""; /** @var string Host name, address, or socket path of PostgreSQL database server (if using PostgreSQL) */ - public $dbPostgreSQLHost = ""; + public $dbPostgreSQLHost = ""; /** @var string Log-in user name for PostgreSQL database server (if using PostgreSQL) */ - public $dbPostgreSQLUser = "arsse"; + public $dbPostgreSQLUser = "arsse"; /** @var string Log-in password for PostgreSQL database server (if using PostgreSQL) */ - public $dbPostgreSQLPass = ""; + public $dbPostgreSQLPass = ""; /** @var integer Listening port for PostgreSQL database server (if using PostgreSQL over TCP) */ - public $dbPostgreSQLPort = 5432; + public $dbPostgreSQLPort = 5432; /** @var string Database name on PostgreSQL database server (if using PostgreSQL) */ - public $dbPostgreSQLDb = "arsse"; + public $dbPostgreSQLDb = "arsse"; /** @var string Schema name in PostgreSQL database (if using PostgreSQL) */ - public $dbPostgreSQLSchema = ""; + public $dbPostgreSQLSchema = ""; /** @var string Service file entry to use (if using PostgreSQL); if using a service entry all above parameters except schema are ignored */ - public $dbPostgreSQLService = ""; + public $dbPostgreSQLService = ""; /** @var string Host name or address of MySQL database server (if using MySQL) */ - public $dbMySQLHost = "localhost"; + public $dbMySQLHost = "localhost"; /** @var string Log-in user name for MySQL database server (if using MySQL) */ - public $dbMySQLUser = "arsse"; + public $dbMySQLUser = "arsse"; /** @var string Log-in password for MySQL database server (if using MySQL) */ - public $dbMySQLPass = ""; + public $dbMySQLPass = ""; /** @var integer Listening port for MySQL database server (if using MySQL over TCP) */ - public $dbMySQLPort = 3306; + public $dbMySQLPort = 3306; /** @var string Database name on MySQL database server (if using MySQL) */ - public $dbMySQLDb = "arsse"; + public $dbMySQLDb = "arsse"; /** @var string Unix domain socket or named pipe to use for MySQL when not connecting over TCP */ - public $dbMySQLSocket = ""; + public $dbMySQLSocket = ""; /** @var string The user management driver to use, currently only "internal". A fully-qualified class name may also be used for custom drivers */ - public $userDriver = "internal"; + public $userDriver = "internal"; /** @var boolean Whether users are already authenticated by the Web server before the application is executed */ - public $userPreAuth = false; + public $userPreAuth = false; /** @var boolean Whether to require successful HTTP authentication before processing API-level authentication for protocols which have any. Normally the Tiny Tiny RSS relies on its own session-token authentication scheme, for example */ - public $userHTTPAuthRequired = false; + public $userHTTPAuthRequired = false; /** @var integer Desired length of temporary user passwords */ - public $userTempPasswordLength = 20; + public $userTempPasswordLength = 20; /** @var boolean Whether invalid or expired API session tokens should prevent logging in when HTTP authentication is used, for protocol which implement their own authentication */ - public $userSessionEnforced = true; + public $userSessionEnforced = true; /** @var \DateInterval Period of inactivity after which log-in sessions should be considered invalid, as an ISO 8601 duration (default: 24 hours) * @see https://en.wikipedia.org/wiki/ISO_8601#Durations */ - public $userSessionTimeout = "PT24H"; + public $userSessionTimeout = "PT24H"; /** @var \DateInterval Maximum lifetime of log-in sessions regardless of activity, as an ISO 8601 duration (default: 7 days); * @see https://en.wikipedia.org/wiki/ISO_8601#Durations */ - public $userSessionLifetime = "P7D"; + public $userSessionLifetime = "P7D"; /** @var string Feed update service driver to use, one of "serial" or "subprocess". A fully-qualified class name may also be used for custom drivers */ - public $serviceDriver = "subprocess"; + public $serviceDriver = "subprocess"; /** @var \DateInterval The interval between checks for new articles, as an ISO 8601 duration * @see https://en.wikipedia.org/wiki/ISO_8601#Durations */ - public $serviceFrequency = "PT2M"; + public $serviceFrequency = "PT2M"; /** @var integer Number of concurrent feed updates to perform */ - public $serviceQueueWidth = 5; + public $serviceQueueWidth = 5; /** @var \DateInterval Number of seconds to wait for data when fetching feeds from foreign servers */ - public $fetchTimeout = 10.0; + public $fetchTimeout = 10.0; /** @var integer Maximum size, in bytes, of data when fetching feeds from foreign servers */ - public $fetchSizeLimit = 2 * 1024 * 1024; + public $fetchSizeLimit = 2 * 1024 * 1024; /** @var boolean Whether to allow the possibility of fetching full article contents using an item's URL. Whether fetching will actually happen is also governed by a per-feed setting */ - public $fetchEnableScraping = true; + public $fetchEnableScraping = true; /** @var string|null User-Agent string to use when fetching feeds from foreign servers */ - public $fetchUserAgentString = null; + public $fetchUserAgentString = null; /** @var \DateInterval|null When to delete a feed from the database after all its subscriptions have been deleted, as an ISO 8601 duration (default: 24 hours; null for never) * @see https://en.wikipedia.org/wiki/ISO_8601#Durations */ - public $purgeFeeds = "PT24H"; + public $purgeFeeds = "PT24H"; /** @var \DateInterval|null 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; null for never) * @see https://en.wikipedia.org/wiki/ISO_8601#Durations */ - public $purgeArticlesRead = "P7D"; + public $purgeArticlesRead = "P7D"; /** @var \DateInterval|null When to delete an unstarred article in the database regardless of its read state, as an ISO 8601 duration (default: 21 days; null for never) * @see https://en.wikipedia.org/wiki/ISO_8601#Durations */ - public $purgeArticlesUnread = "P21D"; + public $purgeArticlesUnread = "P21D"; /** @var string Application name to present to clients during authentication */ - public $httpRealm = "The Advanced RSS Environment"; + public $httpRealm = "The Advanced RSS Environment"; /** @var string Space-separated list of origins from which to allow cross-origin resource sharing */ - public $httpOriginsAllowed = "*"; + public $httpOriginsAllowed = "*"; /** @var string Space-separated list of origins from which to deny cross-origin resource sharing */ - public $httpOriginsDenied = ""; + public $httpOriginsDenied = ""; ### OBSOLETE SETTINGS /** @var \DateInterval|null (OBSOLETE) Number of seconds for SQLite to wait before returning a timeout error when trying to acquire a write lock on the database (zero does not wait) */ - public $dbSQLite3Timeout = null; // previously 60.0 + public $dbSQLite3Timeout = null; // previously 60.0 const TYPE_NAMES = [ Value::T_BOOL => "boolean", @@ -254,10 +254,10 @@ class Conf { $match = explode("|", $match[1]); $nullable = (sizeof($match) > 1); $type = [ - 'string' => Value::T_STRING | Value::M_STRICT, - 'integer' => Value::T_INT | Value::M_STRICT, - 'boolean' => Value::T_BOOL | Value::M_STRICT, - 'float' => Value::T_FLOAT | Value::M_STRICT, + 'string' => Value::T_STRING | Value::M_STRICT, + 'integer' => Value::T_INT | Value::M_STRICT, + 'boolean' => Value::T_BOOL | Value::M_STRICT, + 'float' => Value::T_FLOAT | Value::M_STRICT, '\\DateInterval' => Value::T_INTERVAL | Value::M_LOOSE, ][$match[0]]; if ($nullable) { @@ -283,7 +283,7 @@ class Conf { // it is first converted to an interval and then converted to the numeric type if necessary $mode = $nullable ? Value::M_STRICT | Value::M_NULL : Value::M_STRICT; if (is_string($value)) { - $value = Value::normalize($value, Value::T_INTERVAL | $mode); + $value = Value::normalize($value, Value::T_INTERVAL | $mode); } switch (self::EXPECTED_TYPES[$key] ?? gettype($this->$key)) { case "integer": @@ -299,7 +299,7 @@ class Conf { throw new Conf\Exception("ambiguousDefault", ['param' => $key]); // @codeCoverageIgnore } } - $value = Value::normalize($value, $typeConst); + $value = Value::normalize($value, $typeConst); switch ($key) { case "dbDriver": $driver = $driver ?? Database::DRIVER_NAMES[strtolower($value)] ?? $value; @@ -319,7 +319,7 @@ class Conf { } return $value; } catch (ExceptionType $e) { - $type = static::$types[$key]['const'] & ~(Value::M_STRICT | Value::M_DROP | Value::M_NULL | Value::M_ARRAY); + $type = static::$types[$key]['const'] & ~(Value::M_STRICT | Value::M_DROP | Value::M_NULL | Value::M_ARRAY); throw new Conf\Exception("typeMismatch", ['param' => $key, 'type' => self::TYPE_NAMES[$type], 'file' => $file, 'nullable' => $nullable]); } } diff --git a/lib/Database.php b/lib/Database.php index 24475a6..8bdd437 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -379,7 +379,7 @@ class Database { $max = Date::add(Arsse::$conf->userSessionTimeout, $now)->getTimestamp(); $diff = intdiv($max - $now, 2); // determine if the expiry time is less than half the session timeout into the future - return (($now + $diff) >= $expiry->getTimestamp()); + return ($now + $diff) >= $expiry->getTimestamp(); } /** Creates a new token for the given user in the given class @@ -388,7 +388,7 @@ class Database { * @param string $class The class of the token e.g. the protocol name * @param string|null $id The value of the token; if none is provided a UUID will be generated * @param \DateTimeInterface|null $expires An optional expiry date and time for the token - */ + */ public function tokenCreate(string $user, string $class, string $id = null, \DateTimeInterface $expires = null): string { // If the user isn't authorized to perform this action then throw an exception. if (!Arsse::$user->authorize($user, __FUNCTION__)) { @@ -584,10 +584,10 @@ class Database { return false; } $valid = [ - 'name' => "str", + 'name' => "str", 'parent' => "int", ]; - list($setClause, $setTypes, $setValues) = $this->generateSet($in, $valid); + [$setClause, $setTypes, $setValues] = $this->generateSet($in, $valid); return (bool) $this->db->prepare("UPDATE arsse_folders set $setClause, modified = CURRENT_TIMESTAMP where owner = ? and id = ?", $setTypes, "str", "int")->run($setValues, $user, $id)->changes(); } @@ -881,7 +881,7 @@ class Database { 'order_type' => "strict int", 'pinned' => "strict bool", ]; - list($setClause, $setTypes, $setValues) = $this->generateSet($data, $valid); + [$setClause, $setTypes, $setValues] = $this->generateSet($data, $valid); if (!$setClause) { // if no changes would actually be applied, just return return false; @@ -1220,10 +1220,10 @@ class Database { */ 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, $vId) = $this->generateIn($ids, "str"); - list($cHashUT, $tHashUT, $vHashUT) = $this->generateIn($hashesUT, "str"); - list($cHashUC, $tHashUC, $vHashUC) = $this->generateIn($hashesUC, "str"); - list($cHashTC, $tHashTC, $vHashTC) = $this->generateIn($hashesTC, "str"); + [$cId, $tId, $vId] = $this->generateIn($ids, "str"); + [$cHashUT, $tHashUT, $vHashUT] = $this->generateIn($hashesUT, "str"); + [$cHashUC, $tHashUC, $vHashUC] = $this->generateIn($hashesUC, "str"); + [$cHashTC, $tHashTC, $vHashTC] = $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 = ? and (guid in($cId) or url_title_hash in($cHashUT) or url_content_hash in($cHashUC) or title_content_hash in($cHashTC))", @@ -1242,27 +1242,27 @@ class Database { protected function articleColumns(): array { $greatest = $this->db->sqlToken("greatest"); return [ - 'id' => "arsse_articles.id", - 'edition' => "latest_editions.edition", - 'url' => "arsse_articles.url", - 'title' => "arsse_articles.title", - 'author' => "arsse_articles.author", - 'content' => "arsse_articles.content", - 'guid' => "arsse_articles.guid", - 'fingerprint' => "arsse_articles.url_title_hash || ':' || arsse_articles.url_content_hash || ':' || arsse_articles.title_content_hash", - 'folder' => "coalesce(arsse_subscriptions.folder,0)", - 'subscription' => "arsse_subscriptions.id", - 'feed' => "arsse_subscriptions.feed", - 'starred' => "coalesce(arsse_marks.starred,0)", - 'unread' => "abs(coalesce(arsse_marks.read,0) - 1)", - 'note' => "coalesce(arsse_marks.note,'')", - 'published_date' => "arsse_articles.published", - 'edited_date' => "arsse_articles.edited", - 'modified_date' => "arsse_articles.modified", - 'marked_date' => "$greatest(arsse_articles.modified, coalesce(arsse_marks.modified, '0001-01-01 00:00:00'), coalesce(label_stats.modified, '0001-01-01 00:00:00'))", + 'id' => "arsse_articles.id", + 'edition' => "latest_editions.edition", + 'url' => "arsse_articles.url", + 'title' => "arsse_articles.title", + 'author' => "arsse_articles.author", + 'content' => "arsse_articles.content", + 'guid' => "arsse_articles.guid", + 'fingerprint' => "arsse_articles.url_title_hash || ':' || arsse_articles.url_content_hash || ':' || arsse_articles.title_content_hash", + 'folder' => "coalesce(arsse_subscriptions.folder,0)", + 'subscription' => "arsse_subscriptions.id", + 'feed' => "arsse_subscriptions.feed", + 'starred' => "coalesce(arsse_marks.starred,0)", + 'unread' => "abs(coalesce(arsse_marks.read,0) - 1)", + 'note' => "coalesce(arsse_marks.note,'')", + 'published_date' => "arsse_articles.published", + 'edited_date' => "arsse_articles.edited", + 'modified_date' => "arsse_articles.modified", + 'marked_date' => "$greatest(arsse_articles.modified, coalesce(arsse_marks.modified, '0001-01-01 00:00:00'), coalesce(label_stats.modified, '0001-01-01 00:00:00'))", 'subscription_title' => "coalesce(arsse_subscriptions.title, arsse_feeds.title)", - 'media_url' => "arsse_enclosures.url", - 'media_type' => "arsse_enclosures.type", + 'media_url' => "arsse_enclosures.url", + 'media_type' => "arsse_enclosures.type", ]; } @@ -1359,7 +1359,7 @@ class Database { "unread" => ["unread", "=", "bool", ""], "starred" => ["starred", "=", "bool", ""], ]; - foreach ($options as $m => list($col, $op, $type, $pair)) { + foreach ($options as $m => [$col, $op, $type, $pair]) { if (!$context->$m()) { // context is not being used continue; @@ -1368,7 +1368,7 @@ class Database { if (!$context->$m) { throw new Db\ExceptionInput("tooShort", ['field' => $m, 'action' => $this->caller(), 'min' => 1]); // must have at least one array element } - list($clause, $types, $values) = $this->generateIn($context->$m, $type); + [$clause, $types, $values] = $this->generateIn($context->$m, $type); $q->setWhere("{$colDefs[$col]} $op ($clause)", $types, $values); } elseif ($pair && $context->$pair()) { // option is paired with another which is also being used @@ -1383,7 +1383,7 @@ class Database { } } // further handle exclusionary options if specified - foreach ($options as $m => list($col, $op, $type, $pair)) { + foreach ($options as $m => [$col, $op, $type, $pair]) { if (!method_exists($context->not, $m) || !$context->not->$m()) { // context option is not being used continue; @@ -1392,7 +1392,7 @@ class Database { // for exclusions we don't care if the array is empty continue; } - list($clause, $types, $values) = $this->generateIn($context->not->$m, $type); + [$clause, $types, $values] = $this->generateIn($context->not->$m, $type); $q->setWhereNot("{$colDefs[$col]} $op ($clause)", $types, $values); } elseif ($pair && $context->not->$pair()) { // option is paired with another which is also being used @@ -1409,13 +1409,13 @@ class Database { // handle labels and tags $options = [ 'label' => [ - 'match_col' => "arsse_articles.id", - 'cte_name' => "labelled", - 'cte_cols' => ["article", "label_id", "label_name"], - 'cte_body' => "SELECT m.article, l.id, l.name from arsse_label_members as m join arsse_labels as l on l.id = m.label where l.owner = ? and m.assigned = 1", - 'cte_types' => ["str"], + 'match_col' => "arsse_articles.id", + 'cte_name' => "labelled", + 'cte_cols' => ["article", "label_id", "label_name"], + 'cte_body' => "SELECT m.article, l.id, l.name from arsse_label_members as m join arsse_labels as l on l.id = m.label where l.owner = ? and m.assigned = 1", + 'cte_types' => ["str"], 'cte_values' => [$user], - 'options' => [ + 'options' => [ 'label' => ['use_name' => false, 'multi' => false], 'labels' => ['use_name' => false, 'multi' => true], 'labelName' => ['use_name' => true, 'multi' => false], @@ -1423,13 +1423,13 @@ class Database { ], ], 'tag' => [ - 'match_col' => "arsse_subscriptions.id", - 'cte_name' => "tagged", - 'cte_cols' => ["subscription", "tag_id", "tag_name"], - 'cte_body' => "SELECT m.subscription, t.id, t.name from arsse_tag_members as m join arsse_tags as t on t.id = m.tag where t.owner = ? and m.assigned = 1", - 'cte_types' => ["str"], + 'match_col' => "arsse_subscriptions.id", + 'cte_name' => "tagged", + 'cte_cols' => ["subscription", "tag_id", "tag_name"], + 'cte_body' => "SELECT m.subscription, t.id, t.name from arsse_tag_members as m join arsse_tags as t on t.id = m.tag where t.owner = ? and m.assigned = 1", + 'cte_types' => ["str"], 'cte_values' => [$user], - 'options' => [ + 'options' => [ 'tag' => ['use_name' => false, 'multi' => false], 'tags' => ['use_name' => false, 'multi' => true], 'tagName' => ['use_name' => true, 'multi' => false], @@ -1452,7 +1452,7 @@ class Database { throw new Db\ExceptionInput("tooShort", ['field' => $m, 'action' => $this->caller(), 'min' => 1]); // must have at least one array element } if ($multi) { - list($test, $types, $values) = $this->generateIn($context->$m, $named ? "str" : "int"); + [$test, $types, $values] = $this->generateIn($context->$m, $named ? "str" : "int"); $test = "in ($test)"; } else { $test = "= ?"; @@ -1464,7 +1464,7 @@ class Database { if ($context->not->$m()) { $seen = true; if ($multi) { - list($test, $types, $values) = $this->generateIn($context->not->$m, $named ? "str" : "int"); + [$test, $types, $values] = $this->generateIn($context->not->$m, $named ? "str" : "int"); $test = "in ($test)"; } else { $test = "= ?"; @@ -1496,7 +1496,7 @@ class Database { $q->setWhere("coalesce(arsse_subscriptions.folder,0) in (select folder from folders)"); } if ($context->folders()) { - list($inClause, $inTypes, $inValues) = $this->generateIn($context->folders, "int"); + [$inClause, $inTypes, $inValues] = $this->generateIn($context->folders, "int"); // add a common table expression to list the folders and their children so that we select from the entire subtree $q->setCTE("folders_multi(folder)", "SELECT id as folder from (select id from (select 0 as id union select id from arsse_folders where owner = ?) as f where id in ($inClause)) as folders_multi union select id from arsse_folders join folders_multi on coalesce(parent,0) = folder", ["str", $inTypes], [$user, $inValues]); // limit subscriptions to the listed folders @@ -1509,7 +1509,7 @@ class Database { $q->setWhereNot("coalesce(arsse_subscriptions.folder,0) in (select folder from folders_excluded)"); } if ($context->not->folders()) { - list($inClause, $inTypes, $inValues) = $this->generateIn($context->not->folders, "int"); + [$inClause, $inTypes, $inValues] = $this->generateIn($context->not->folders, "int"); // add a common table expression to list the folders and their children so that we select from the entire subtree $q->setCTE("folders_multi_excluded(folder)", "SELECT id as folder from (select id from (select 0 as id union select id from arsse_folders where owner = ?) as f where id in ($inClause)) as folders_multi_excluded union select id from arsse_folders join folders_multi_excluded on coalesce(parent,0) = folder", ["str", $inTypes], [$user, $inValues]); // limit subscriptions to the listed folders @@ -1623,9 +1623,9 @@ class Database { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } $data = [ - 'read' => $data['read'] ?? null, + 'read' => $data['read'] ?? null, 'starred' => $data['starred'] ?? null, - 'note' => $data['note'] ?? null, + 'note' => $data['note'] ?? null, ]; if (!isset($data['read']) && !isset($data['starred']) && !isset($data['note'])) { return 0; @@ -1664,7 +1664,7 @@ class Database { $data = array_filter($data, function($v) { return isset($v); }); - list($set, $setTypes, $setValues) = $this->generateSet($data, ['starred' => "bool", 'note' => "str"]); + [$set, $setTypes, $setValues] = $this->generateSet($data, ['starred' => "bool", 'note' => "str"]); $q->setBody("UPDATE arsse_marks set touched = 1, $set where article in(select article from target_articles) and subscription in(select distinct subscription from target_articles)", $setTypes, $setValues); $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues()); } @@ -1688,7 +1688,7 @@ class Database { $data = array_filter($data, function($v) { return isset($v); }); - list($set, $setTypes, $setValues) = $this->generateSet($data, ['read' => "bool", 'starred' => "bool", 'note' => "str"]); + [$set, $setTypes, $setValues] = $this->generateSet($data, ['read' => "bool", 'starred' => "bool", 'note' => "str"]); $q->setBody("UPDATE arsse_marks set $set, modified = CURRENT_TIMESTAMP where article in(select article from target_articles) and subscription in(select distinct subscription from target_articles)", $setTypes, $setValues); $out = $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->changes(); } @@ -1860,7 +1860,7 @@ class Database { public function editionArticle(int ...$edition): array { $out = []; $context = (new Context)->editions($edition); - list($in, $inTypes, $inValues) = $this->generateIn($context->editions, "int"); + [$in, $inTypes, $inValues] = $this->generateIn($context->editions, "int"); $out = $this->db->prepare("SELECT id as edition, article from arsse_editions where id in($in)", $inTypes)->run($inValues)->getAll(); return $out ? array_combine(array_column($out, "edition"), array_column($out, "article")) : []; } @@ -2018,7 +2018,7 @@ class Database { $valid = [ 'name' => "str", ]; - list($setClause, $setTypes, $setValues) = $this->generateSet($data, $valid); + [$setClause, $setTypes, $setValues] = $this->generateSet($data, $valid); if (!$setClause) { // if no changes would actually be applied, just return return false; @@ -2086,7 +2086,7 @@ class Database { $articles = array_column($articles, "id"); } // prepare up to three queries: removing requires one, adding two, and replacing three - list($inClause, $inTypes, $inValues) = $this->generateIn($articles, "int"); + [$inClause, $inTypes, $inValues] = $this->generateIn($articles, "int"); $updateQ = "UPDATE arsse_label_members set assigned = ?, modified = CURRENT_TIMESTAMP where label = ? and assigned <> ? and article %in% ($inClause)"; $updateT = ["bool", "int", "bool", $inTypes]; $insertQ = "INSERT INTO arsse_label_members(label,article,subscription) SELECT ?,a.id,s.id from arsse_articles as a join arsse_subscriptions as s on a.feed = s.feed where s.owner = ? and a.id not in (select article from arsse_label_members where label = ?) and a.id in ($inClause)"; @@ -2112,7 +2112,7 @@ class Database { // execute them in a transaction $out = 0; $tr = $this->begin(); - foreach ($qList as list($q, $t, $v)) { + foreach ($qList as [$q, $t, $v]) { $out += $this->db->prepare($q, ...$t)->run(...$v)->changes(); } $tr->commit(); @@ -2321,7 +2321,7 @@ class Database { $valid = [ 'name' => "str", ]; - list($setClause, $setTypes, $setValues) = $this->generateSet($data, $valid); + [$setClause, $setTypes, $setValues] = $this->generateSet($data, $valid); if (!$setClause) { // if no changes would actually be applied, just return return false; @@ -2385,7 +2385,7 @@ class Database { } } // prepare up to three queries: removing requires one, adding two, and replacing three - list($inClause, $inTypes, $inValues) = $this->generateIn($subscriptions, "int"); + [$inClause, $inTypes, $inValues] = $this->generateIn($subscriptions, "int"); $updateQ = "UPDATE arsse_tag_members set assigned = ?, modified = CURRENT_TIMESTAMP where tag = ? and assigned <> ? and subscription in (select id from arsse_subscriptions where owner = ? and id %in% ($inClause))"; $updateT = ["bool", "int", "bool", "str", $inTypes]; $insertQ = "INSERT INTO arsse_tag_members(tag,subscription) SELECT ?,id from arsse_subscriptions where id not in (select subscription from arsse_tag_members where tag = ?) and owner = ? and id in ($inClause)"; @@ -2411,7 +2411,7 @@ class Database { // execute them in a transaction $out = 0; $tr = $this->begin(); - foreach ($qList as list($q, $t, $v)) { + foreach ($qList as [$q, $t, $v]) { $out += $this->db->prepare($q, ...$t)->run(...$v)->changes(); } $tr->commit(); diff --git a/lib/Db/AbstractDriver.php b/lib/Db/AbstractDriver.php index fd377b2..2a6a973 100644 --- a/lib/Db/AbstractDriver.php +++ b/lib/Db/AbstractDriver.php @@ -40,9 +40,9 @@ abstract class AbstractDriver implements Driver { 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 - } elseif ($sql==="") { + } elseif ($sql === "") { throw new Exception("updateFileIncomplete", ['file' => $file, 'driver_name' => $this->driverName(), 'current' => $a]); } try { @@ -50,7 +50,7 @@ abstract class AbstractDriver implements Driver { } catch (\Throwable $e) { throw new Exception("updateFileError", ['file' => $file, 'driver_name' => $this->driverName(), 'current' => $a, 'message' => $e->getMessage()]); } - 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) { diff --git a/lib/Db/AbstractStatement.php b/lib/Db/AbstractStatement.php index 45b6801..1aa7e20 100644 --- a/lib/Db/AbstractStatement.php +++ b/lib/Db/AbstractStatement.php @@ -13,12 +13,12 @@ abstract class AbstractStatement implements Statement { use SQLState; const TYPE_NORM_MAP = [ - self::T_INTEGER => ValueInfo::M_NULL | ValueInfo::T_INT, - self::T_STRING => ValueInfo::M_NULL | ValueInfo::T_STRING, - self::T_BOOLEAN => ValueInfo::M_NULL | ValueInfo::T_BOOL, - self::T_DATETIME => ValueInfo::M_NULL | ValueInfo::T_DATE, - self::T_FLOAT => ValueInfo::M_NULL | ValueInfo::T_FLOAT, - self::T_BINARY => ValueInfo::M_NULL | ValueInfo::T_STRING, + self::T_INTEGER => ValueInfo::M_NULL | ValueInfo::T_INT, + self::T_STRING => ValueInfo::M_NULL | ValueInfo::T_STRING, + self::T_BOOLEAN => ValueInfo::M_NULL | ValueInfo::T_BOOL, + self::T_DATETIME => ValueInfo::M_NULL | ValueInfo::T_DATE, + self::T_FLOAT => ValueInfo::M_NULL | ValueInfo::T_FLOAT, + self::T_BINARY => ValueInfo::M_NULL | ValueInfo::T_STRING, self::T_NOT_NULL + self::T_INTEGER => ValueInfo::T_INT, self::T_NOT_NULL + self::T_STRING => ValueInfo::T_STRING, self::T_NOT_NULL + self::T_BOOLEAN => ValueInfo::T_BOOL, @@ -78,7 +78,7 @@ abstract class AbstractStatement implements Statement { $value = $this->cast($value, $this->types[$a]); $this->bindValue($value, $this->types[$a] % self::T_NOT_NULL, ++$a); } else { - throw new Exception("paramTypeMissing", $a+1); + throw new Exception("paramTypeMissing", $a + 1); } } // once all values are bound, check that all parameters have been supplied values and bind null for any missing ones diff --git a/lib/Db/MySQL/Driver.php b/lib/Db/MySQL/Driver.php index 6be8c3f..49ed00d 100644 --- a/lib/Db/MySQL/Driver.php +++ b/lib/Db/MySQL/Driver.php @@ -163,7 +163,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { $this->db->options(\MYSQLI_OPT_CONNECT_TIMEOUT, ceil(Arsse::$conf->dbTimeoutConnect)); @$this->db->real_connect($host, $user, $password, $db, $port, $socket); if ($this->db->connect_errno) { - list($excClass, $excMsg, $excData) = $this->buildConnectionException($this->db->connect_errno, $this->db->connect_error); + [$excClass, $excMsg, $excData] = $this->buildConnectionException($this->db->connect_errno, $this->db->connect_error); throw new $excClass($excMsg, $excData); } $this->db->set_charset("utf8mb4"); @@ -184,11 +184,11 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { do { if ($this->db->sqlstate !== "00000") { if ($this->db->sqlstate === "HY000") { - list($excClass, $excMsg, $excData) = $this->buildEngineException($this->db->errno, $this->db->error); + [$excClass, $excMsg, $excData] = $this->buildEngineException($this->db->errno, $this->db->error); } else { - list($excClass, $excMsg, $excData) = $this->buildStandardException($this->db->sqlstate, $this->db->error); + [$excClass, $excMsg, $excData] = $this->buildStandardException($this->db->sqlstate, $this->db->error); } - $e = new $excClass($excMsg, $excData, $e); + $e = new $excClass($excMsg, $excData, $e); } $r = $this->db->store_result(); } while ($this->db->more_results() && $this->db->next_result()); diff --git a/lib/Db/MySQL/PDODriver.php b/lib/Db/MySQL/PDODriver.php index a294710..e669fca 100644 --- a/lib/Db/MySQL/PDODriver.php +++ b/lib/Db/MySQL/PDODriver.php @@ -34,7 +34,7 @@ class PDODriver extends Driver { $msg = $e->getMessage(); $code = (int) substr($msg, 17, 4); $msg = substr($msg, 23); - list($excClass, $excMsg, $excData) = $this->buildConnectionException($code, $msg); + [$excClass, $excMsg, $excData] = $this->buildConnectionException($code, $msg); throw new $excClass($excMsg, $excData); } } diff --git a/lib/Db/MySQL/Result.php b/lib/Db/MySQL/Result.php index d2a2619..45e8225 100644 --- a/lib/Db/MySQL/Result.php +++ b/lib/Db/MySQL/Result.php @@ -44,6 +44,6 @@ class Result extends \JKingWeb\Arsse\Db\AbstractResult { public function valid() { $this->cur = $this->set ? $this->set->fetch_assoc() : null; - return ($this->cur !== null); + return $this->cur !== null; } } diff --git a/lib/Db/MySQL/Statement.php b/lib/Db/MySQL/Statement.php index b6c6ceb..02b56bd 100644 --- a/lib/Db/MySQL/Statement.php +++ b/lib/Db/MySQL/Statement.php @@ -37,7 +37,7 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement { protected function prepare(string $query): bool { $this->st = $this->db->prepare($query); if (!$this->st) { // @codeCoverageIgnore - list($excClass, $excMsg, $excData) = $this->buildEngineException($this->db->errno, $this->db->error); // @codeCoverageIgnore + [$excClass, $excMsg, $excData] = $this->buildEngineException($this->db->errno, $this->db->error); // @codeCoverageIgnore throw new $excClass($excMsg, $excData); // @codeCoverageIgnore } return true; @@ -76,9 +76,9 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement { // check for errors if ($this->st->sqlstate !== "00000") { if ($this->st->sqlstate === "HY000") { - list($excClass, $excMsg, $excData) = $this->buildEngineException($this->st->errno, $this->st->error); + [$excClass, $excMsg, $excData] = $this->buildEngineException($this->st->errno, $this->st->error); } else { - list($excClass, $excMsg, $excData) = $this->buildStandardException($this->st->sqlstate, $this->st->error); + [$excClass, $excMsg, $excData] = $this->buildStandardException($this->st->sqlstate, $this->st->error); } throw new $excClass($excMsg, $excData); } diff --git a/lib/Db/PDODriver.php b/lib/Db/PDODriver.php index df5dcc3..df01bac 100644 --- a/lib/Db/PDODriver.php +++ b/lib/Db/PDODriver.php @@ -14,7 +14,7 @@ trait PDODriver { $this->db->exec($query); return true; } catch (\PDOException $e) { - list($excClass, $excMsg, $excData) = $this->buildPDOException(); + [$excClass, $excMsg, $excData] = $this->buildPDOException(); throw new $excClass($excMsg, $excData); } } @@ -23,7 +23,7 @@ trait PDODriver { try { $r = $this->db->query($query); } catch (\PDOException $e) { - list($excClass, $excMsg, $excData) = $this->buildPDOException(); + [$excClass, $excMsg, $excData] = $this->buildPDOException(); throw new $excClass($excMsg, $excData); } return new PDOResult($this->db, $r); diff --git a/lib/Db/PDOResult.php b/lib/Db/PDOResult.php index 276e12c..6702301 100644 --- a/lib/Db/PDOResult.php +++ b/lib/Db/PDOResult.php @@ -45,6 +45,6 @@ class PDOResult extends AbstractResult { public function valid() { $this->cur = $this->set->fetch(\PDO::FETCH_ASSOC); - return ($this->cur !== false); + return $this->cur !== false; } } diff --git a/lib/Db/PDOStatement.php b/lib/Db/PDOStatement.php index 2175231..132e1e7 100644 --- a/lib/Db/PDOStatement.php +++ b/lib/Db/PDOStatement.php @@ -34,7 +34,7 @@ abstract class PDOStatement extends AbstractStatement { $this->st = $this->db->prepare($query); return true; } catch (\PDOException $e) { // @codeCoverageIgnore - list($excClass, $excMsg, $excData) = $this->buildPDOException(); // @codeCoverageIgnore + [$excClass, $excMsg, $excData] = $this->buildPDOException(); // @codeCoverageIgnore throw new $excClass($excMsg, $excData); // @codeCoverageIgnore } } @@ -49,7 +49,7 @@ abstract class PDOStatement extends AbstractStatement { try { $this->st->execute(); } catch (\PDOException $e) { - list($excClass, $excMsg, $excData) = $this->buildPDOException(true); + [$excClass, $excMsg, $excData] = $this->buildPDOException(true); throw new $excClass($excMsg, $excData); } return new PDOResult($this->db, $this->st); diff --git a/lib/Db/PostgreSQL/Driver.php b/lib/Db/PostgreSQL/Driver.php index f06518e..a06b6a5 100644 --- a/lib/Db/PostgreSQL/Driver.php +++ b/lib/Db/PostgreSQL/Driver.php @@ -37,9 +37,9 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { public static function makeConnectionString(bool $pdo, string $user, string $pass, string $db, string $host, int $port, string $service): string { $base = [ - 'client_encoding' => "UTF8", + 'client_encoding' => "UTF8", 'application_name' => "arsse", - 'connect_timeout' => (string) (int) ceil(Arsse::$conf->dbTimeoutConnect), + 'connect_timeout' => (string) (int) ceil(Arsse::$conf->dbTimeoutConnect), ]; $out = []; if ($service != "") { @@ -198,7 +198,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { pg_send_query($this->db, $query); while ($result = pg_get_result($this->db)) { if (($code = pg_result_error_field($result, \PGSQL_DIAG_SQLSTATE)) && isset($code) && $code) { - list($excClass, $excMsg, $excData) = $this->buildStandardException($code, pg_result_error($result)); + [$excClass, $excMsg, $excData] = $this->buildStandardException($code, pg_result_error($result)); throw new $excClass($excMsg, $excData); } } @@ -210,7 +210,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { if (is_resource($r)) { return new Result($this->db, $r); } else { - list($excClass, $excMsg, $excData) = $r; + [$excClass, $excMsg, $excData] = $r; throw new $excClass($excMsg, $excData); } } diff --git a/lib/Db/PostgreSQL/PDODriver.php b/lib/Db/PostgreSQL/PDODriver.php index fe6f0a5..93daf66 100644 --- a/lib/Db/PostgreSQL/PDODriver.php +++ b/lib/Db/PostgreSQL/PDODriver.php @@ -22,7 +22,7 @@ class PDODriver extends Driver { $dsn = $this->makeconnectionString(true, $user, $pass, $db, $host, $port, $service); try { $this->db = new \PDO("pgsql:$dsn", $user, $pass, [ - \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_PERSISTENT => true, ]); } catch (\PDOException $e) { @@ -53,7 +53,6 @@ class PDODriver extends Driver { } } - public static function driverName(): string { return Arsse::$lang->msg("Driver.Db.PostgreSQLPDO.Name"); } diff --git a/lib/Db/PostgreSQL/Result.php b/lib/Db/PostgreSQL/Result.php index 299cf9f..03dba17 100644 --- a/lib/Db/PostgreSQL/Result.php +++ b/lib/Db/PostgreSQL/Result.php @@ -41,6 +41,6 @@ class Result extends \JKingWeb\Arsse\Db\AbstractResult { public function valid() { $this->cur = pg_fetch_row($this->r, null, \PGSQL_ASSOC); - return ($this->cur !== false); + return $this->cur !== false; } } diff --git a/lib/Db/PostgreSQL/Statement.php b/lib/Db/PostgreSQL/Statement.php index 4e062f2..058ca2e 100644 --- a/lib/Db/PostgreSQL/Statement.php +++ b/lib/Db/PostgreSQL/Statement.php @@ -38,7 +38,7 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement { if (is_resource($r)) { return new Result($this->db, $r); } else { - list($excClass, $excMsg, $excData) = $r; + [$excClass, $excMsg, $excData] = $r; throw new $excClass($excMsg, $excData); } } diff --git a/lib/Db/ResultEmpty.php b/lib/Db/ResultEmpty.php index 569400e..f0f23de 100644 --- a/lib/Db/ResultEmpty.php +++ b/lib/Db/ResultEmpty.php @@ -9,7 +9,7 @@ namespace JKingWeb\Arsse\Db; class ResultEmpty extends AbstractResult { protected $changes = 0; protected $id = 0; - + public function __construct(int $changes = 0, int $id = 0) { $this->changes = $changes; $this->id = $id; diff --git a/lib/Db/SQLState.php b/lib/Db/SQLState.php index 7e4fa29..30d9f2c 100644 --- a/lib/Db/SQLState.php +++ b/lib/Db/SQLState.php @@ -6,10 +6,6 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Db; -use JKingWeb\Arsse\Db\Exception; -use JKingWeb\Arsse\Db\ExceptionInput; -use JKingWeb\Arsse\Db\ExceptionTimeout; - trait SQLState { protected static function buildStandardException(string $code, string $msg): array { switch ($code) { diff --git a/lib/Db/SQLite3/Driver.php b/lib/Db/SQLite3/Driver.php index d76dedd..cb23ac6 100644 --- a/lib/Db/SQLite3/Driver.php +++ b/lib/Db/SQLite3/Driver.php @@ -98,7 +98,6 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { } } - public static function driverName(): string { return Arsse::$lang->msg("Driver.Db.SQLite3.Name"); } @@ -146,7 +145,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { try { return (bool) $this->db->exec($query); } catch (\Exception $e) { - list($excClass, $excMsg, $excData) = $this->buildException(); + [$excClass, $excMsg, $excData] = $this->buildException(); throw new $excClass($excMsg, $excData); } } @@ -155,7 +154,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { try { $r = $this->db->query($query); } catch (\Exception $e) { - list($excClass, $excMsg, $excData) = $this->buildException(); + [$excClass, $excMsg, $excData] = $this->buildException(); throw new $excClass($excMsg, $excData); } $changes = $this->db->changes(); diff --git a/lib/Db/SQLite3/PDODriver.php b/lib/Db/SQLite3/PDODriver.php index c590d51..506c46a 100644 --- a/lib/Db/SQLite3/PDODriver.php +++ b/lib/Db/SQLite3/PDODriver.php @@ -37,7 +37,6 @@ class PDODriver extends AbstractPDODriver { } } - public static function driverName(): string { return Arsse::$lang->msg("Driver.Db.SQLite3PDO.Name"); } diff --git a/lib/Db/SQLite3/Result.php b/lib/Db/SQLite3/Result.php index 6b7aab2..ad8aa05 100644 --- a/lib/Db/SQLite3/Result.php +++ b/lib/Db/SQLite3/Result.php @@ -44,6 +44,6 @@ class Result extends \JKingWeb\Arsse\Db\AbstractResult { public function valid() { $this->cur = $this->set->fetchArray(\SQLITE3_ASSOC); - return ($this->cur !== false); + return $this->cur !== false; } } diff --git a/lib/Db/SQLite3/Statement.php b/lib/Db/SQLite3/Statement.php index d2eee30..3374689 100644 --- a/lib/Db/SQLite3/Statement.php +++ b/lib/Db/SQLite3/Statement.php @@ -37,7 +37,7 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement { $this->st = $this->db->prepare($query); return true; } catch (\Exception $e) { // @codeCoverageIgnore - list($excClass, $excMsg, $excData) = $this->buildException(); // @codeCoverageIgnore + [$excClass, $excMsg, $excData] = $this->buildException(); // @codeCoverageIgnore throw new $excClass($excMsg, $excData); // @codeCoverageIgnore } } @@ -56,7 +56,7 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement { try { $r = $this->st->execute(); } catch (\Exception $e) { - list($excClass, $excMsg, $excData) = $this->buildException(); + [$excClass, $excMsg, $excData] = $this->buildException(); throw new $excClass($excMsg, $excData); } $changes = $this->db->changes(); diff --git a/lib/Feed.php b/lib/Feed.php index e8e5dac..e6a8ebc 100644 --- a/lib/Feed.php +++ b/lib/Feed.php @@ -221,8 +221,8 @@ class Feed { // if the two items have the same ID or any one hash matches, they are two versions of the same item if ( ($item->id && $check->id && $item->id === $check->id) || - ($item->urlTitleHash && $item->urlTitleHash === $check->urlTitleHash) || - ($item->urlContentHash && $item->urlContentHash === $check->urlContentHash) || + ($item->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... @@ -259,7 +259,7 @@ class Feed { // get as many of the latest articles in the database as there are in the 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); + [$this->newItems, $this->changedItems] = $this->matchItems($items, $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 = []; @@ -278,7 +278,7 @@ class Feed { } } $articles = Arsse::$db->feedMatchIds($feedID, $ids, $hashesUT, $hashesUC, $hashesTC)->getAll(); - list($this->newItems, $changed) = $this->matchItems($this->newItems, $articles); + [$this->newItems, $changed] = $this->matchItems($this->newItems, $articles); // merge the two change-lists, preserving keys $this->changedItems = array_combine(array_merge(array_keys($this->changedItems), array_keys($changed)), array_merge($this->changedItems, $changed)); } @@ -286,7 +286,7 @@ class Feed { } protected function matchItems(array $items, array $articles): array { - $new = $edited = []; + $new = $edited = []; // iterate through the articles and for each determine whether it is existing, edited, or entirely new foreach ($items as $i) { $found = false; @@ -299,8 +299,8 @@ class Feed { // the item matches if the GUID matches... ($i->id && $i->id === $a['guid']) || // ... or if any one of the hashes match - ($i->urlTitleHash && $i->urlTitleHash === $a['url_title_hash']) || - ($i->urlContentHash && $i->urlContentHash === $a['url_content_hash']) || + ($i->urlTitleHash && $i->urlTitleHash === $a['url_title_hash']) || + ($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']) { @@ -348,7 +348,7 @@ class Feed { $dates = $this->gatherDates(); if (sizeof($dates) > 3) { for ($a = 0; $a < 3; $a++) { - $diff = $dates[$a] - $dates[$a+1]; + $diff = $dates[$a] - $dates[$a + 1]; $offsets[] = $this->normalizeDateDiff($diff); } if ($offsets[0] === $offsets[1] || $offsets[0] === $offsets[2]) { diff --git a/lib/Feed/Exception.php b/lib/Feed/Exception.php index 00c7652..39936b3 100644 --- a/lib/Feed/Exception.php +++ b/lib/Feed/Exception.php @@ -12,8 +12,8 @@ use GuzzleHttp\Exception\TooManyRedirectsException; use PicoFeed\PicoFeedException; class Exception extends \JKingWeb\Arsse\AbstractException { - const CURL_ERROR_MAP = [1=>"invalidUrl",3=>"invalidUrl",5=>"transmissionError","connectionFailed","connectionFailed","transmissionError","forbidden","unauthorized","transmissionError","transmissionError","transmissionError","transmissionError","connectionFailed","connectionFailed","transmissionError","transmissionError","transmissionError","transmissionError","transmissionError","invalidUrl","transmissionError","transmissionError","transmissionError","transmissionError",28=>"timeout","transmissionError","transmissionError","transmissionError","transmissionError","transmissionError",35=>"invalidCertificate","transmissionError","transmissionError","transmissionError","transmissionError",45=>"transmissionError","unauthorized","maxRedirect",52=>"transmissionError","invalidCertificate","invalidCertificate","transmissionError","transmissionError",58=>"invalidCertificate","invalidCertificate","invalidCertificate","transmissionError","invalidUrl","transmissionError","invalidCertificate","transmissionError","invalidCertificate","forbidden","invalidUrl","forbidden","transmissionError",73=>"transmissionError","transmissionError",77=>"invalidCertificate","invalidUrl",90=>"invalidCertificate","invalidCertificate","transmissionError",94=>"unauthorized","transmissionError","connectionFailed"]; - const HTTP_ERROR_MAP = [401=>"unauthorized",403=>"forbidden",404=>"invalidUrl",408=>"timeout",410=>"invalidUrl",414=>"invalidUrl",451=>"invalidUrl"]; + const CURL_ERROR_MAP = [1 => "invalidUrl",3 => "invalidUrl",5 => "transmissionError","connectionFailed","connectionFailed","transmissionError","forbidden","unauthorized","transmissionError","transmissionError","transmissionError","transmissionError","connectionFailed","connectionFailed","transmissionError","transmissionError","transmissionError","transmissionError","transmissionError","invalidUrl","transmissionError","transmissionError","transmissionError","transmissionError",28 => "timeout","transmissionError","transmissionError","transmissionError","transmissionError","transmissionError",35 => "invalidCertificate","transmissionError","transmissionError","transmissionError","transmissionError",45 => "transmissionError","unauthorized","maxRedirect",52 => "transmissionError","invalidCertificate","invalidCertificate","transmissionError","transmissionError",58 => "invalidCertificate","invalidCertificate","invalidCertificate","transmissionError","invalidUrl","transmissionError","invalidCertificate","transmissionError","invalidCertificate","forbidden","invalidUrl","forbidden","transmissionError",73 => "transmissionError","transmissionError",77 => "invalidCertificate","invalidUrl",90 => "invalidCertificate","invalidCertificate","transmissionError",94 => "unauthorized","transmissionError","connectionFailed"]; + const HTTP_ERROR_MAP = [401 => "unauthorized",403 => "forbidden",404 => "invalidUrl",408 => "timeout",410 => "invalidUrl",414 => "invalidUrl",451 => "invalidUrl"]; public function __construct($url, \Throwable $e) { if ($e instanceof BadResponseException) { diff --git a/lib/ImportExport/AbstractImportExport.php b/lib/ImportExport/AbstractImportExport.php index 19fa5fc..22c1f2b 100644 --- a/lib/ImportExport/AbstractImportExport.php +++ b/lib/ImportExport/AbstractImportExport.php @@ -17,7 +17,7 @@ abstract class AbstractImportExport { throw new UserException("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); } // first extract useful information from the input - list($feeds, $folders) = $this->parse($data, $flat); + [$feeds, $folders] = $this->parse($data, $flat); $folderMap = []; foreach ($folders as $f) { // check to make sure folder names are all valid @@ -42,7 +42,7 @@ abstract class AbstractImportExport { $tr = Arsse::$db->begin(); // get current state of database $foldersDb = iterator_to_array(Arsse::$db->folderList($user)); - $feedsDb = iterator_to_array(Arsse::$db->subscriptionList($user)); + $feedsDb = iterator_to_array(Arsse::$db->subscriptionList($user)); $tagsDb = iterator_to_array(Arsse::$db->tagList($user)); // reconcile folders $folderMap = [0 => 0]; diff --git a/lib/Lang.php b/lib/Lang.php index b636f3b..920ddda 100644 --- a/lib/Lang.php +++ b/lib/Lang.php @@ -97,7 +97,7 @@ class Lang { } $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 = []; } elseif (!is_array($vars)) { @@ -108,7 +108,7 @@ class Lang { throw new Lang\Exception("stringInvalid", ['error' => $this->formatter->getErrorMessage(), 'msgID' => $msgID, 'fileList' => implode(", ", $this->loaded)]); } $msg = $this->formatter->format($vars); - if ($msg===false) { + if ($msg === false) { throw new Lang\Exception("dataInvalid", ['error' => $this->formatter->getErrorMessage(), 'msgID' => $msgID, 'fileList' => implode(", ", $this->loaded)]); // @codeCoverageIgnore } return $msg; @@ -148,7 +148,7 @@ class Lang { // trim the returned file paths to return just the language tag $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); + $file = substr($file, strrpos($file, "/") + 1); return strtolower(substr($file, 0, strrpos($file, "."))); }, $out); // sort the results diff --git a/lib/Misc/Query.php b/lib/Misc/Query.php index 95b5c2c..a2965dc 100644 --- a/lib/Misc/Query.php +++ b/lib/Misc/Query.php @@ -24,7 +24,6 @@ class Query { protected $limit = 0; protected $offset = 0; - public function __construct(string $body = "", $types = null, $values = null) { $this->setBody($body, $types, $values); } diff --git a/lib/Misc/URL.php b/lib/Misc/URL.php index 4a4459c..df16e6f 100644 --- a/lib/Misc/URL.php +++ b/lib/Misc/URL.php @@ -77,7 +77,7 @@ class URL { $c = $part[$pos]; if ($c === "%") { // the % character signals an encoded character... - $d = substr($part, $pos+1, 2); + $d = substr($part, $pos + 1, 2); if (!preg_match("/^[0-9a-fA-F]{2}$/", $d)) { // unless there are fewer than two characters left in the string or the two characters are not hex digits $d = ord($c); diff --git a/lib/Misc/ValueInfo.php b/lib/Misc/ValueInfo.php index 75a81ba..806f6a3 100644 --- a/lib/Misc/ValueInfo.php +++ b/lib/Misc/ValueInfo.php @@ -11,30 +11,30 @@ use JKingWeb\Arsse\ExceptionType; class ValueInfo { // universal const VALID = 1 << 0; - const NULL = 1 << 1; + const NULL = 1 << 1; // integers - const ZERO = 1 << 2; - const NEG = 1 << 3; + const ZERO = 1 << 2; + const NEG = 1 << 3; const FLOAT = 1 << 4; // strings const EMPTY = 1 << 2; const WHITE = 1 << 3; // normalization types - const T_MIXED = 0; // pass through unchanged - const T_NULL = 1; // convert to null - const T_BOOL = 2; // convert to boolean - const T_INT = 3; // convert to integer - const T_FLOAT = 4; // convert to floating point - const T_DATE = 5; // convert to DateTimeInterface instance - const T_STRING = 6; // convert to string - const T_ARRAY = 7; // convert to array + const T_MIXED = 0; // pass through unchanged + const T_NULL = 1; // convert to null + const T_BOOL = 2; // convert to boolean + const T_INT = 3; // convert to integer + const T_FLOAT = 4; // convert to floating point + const T_DATE = 5; // convert to DateTimeInterface instance + const T_STRING = 6; // convert to string + const T_ARRAY = 7; // convert to array const T_INTERVAL = 8; // convert to time interval // normalization modes - const M_LOOSE = 0; - const M_NULL = 1 << 28; // pass nulls through regardless of target type - const M_DROP = 1 << 29; // drop the value (return null) if the type doesn't match - const M_STRICT = 1 << 30; // throw an exception if the type doesn't match - const M_ARRAY = 1 << 31; // the value should be a flat array of values of the specified type; indexed and associative are both acceptable + const M_LOOSE = 0; + const M_NULL = 1 << 28; // pass nulls through regardless of target type + const M_DROP = 1 << 29; // drop the value (return null) if the type doesn't match + const M_STRICT = 1 << 30; // throw an exception if the type doesn't match + const M_ARRAY = 1 << 31; // the value should be a flat array of values of the specified type; indexed and associative are both acceptable // symbolic date and time formats const DATE_FORMATS = [ // in out 'iso8601' => ["!Y-m-d\TH:i:s", "Y-m-d\TH:i:s\Z" ], // NOTE: ISO 8601 dates require special input processing because of varying formats for timezone offsets @@ -50,10 +50,10 @@ class ValueInfo { public static function normalize($value, int $type, string $dateInFormat = null, $dateOutFormat = null) { $allowNull = ($type & self::M_NULL); - $strict = ($type & (self::M_STRICT | self::M_DROP)); - $drop = ($type & self::M_DROP); - $arrayVal = ($type & self::M_ARRAY); - $type = ($type & ~(self::M_NULL | self::M_DROP | self::M_STRICT | self::M_ARRAY)); + $strict = ($type & (self::M_STRICT | self::M_DROP)); + $drop = ($type & self::M_DROP); + $arrayVal = ($type & self::M_ARRAY); + $type = ($type & ~(self::M_NULL | self::M_DROP | self::M_STRICT | self::M_ARRAY)); // if the value is null and this is allowed, simply return if ($allowNull && is_null($value)) { return null; @@ -166,7 +166,7 @@ class ValueInfo { throw new ExceptionType("strictFailure", $type); } $out = filter_var($value, \FILTER_VALIDATE_FLOAT); - if ($strict && $out===false) { + if ($strict && $out === false) { // if strict and input is not a float, this is an error if ($drop) { return null; diff --git a/lib/REST.php b/lib/REST.php index b375f3c..317a650 100644 --- a/lib/REST.php +++ b/lib/REST.php @@ -6,7 +6,6 @@ declare(strict_types=1); namespace JKingWeb\Arsse; -use JKingWeb\Arsse\Arsse; use JKingWeb\Arsse\Misc\URL; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ServerRequestInterface; @@ -71,7 +70,7 @@ class REST { $req = $req ?? ServerRequestFactory::fromGlobals(); // find the API to handle try { - list($api, $target, $class) = $this->apiMatch($req->getRequestTarget(), $this->apis); + [$api, $target, $class] = $this->apiMatch($req->getRequestTarget(), $this->apis); // authenticate the request pre-emptively $req = $this->authenticateRequest($req); // modify the request to have an uppercase method and a stripped target @@ -108,7 +107,7 @@ class REST { // find a match foreach ($map as $id => $api) { // first try a simple substring match - if (strpos($url, $api['match'])===0) { + if (strpos($url, $api['match']) === 0) { // if it matches, perform a more rigorous match and then strip off any defined prefix $pattern = "<^".preg_quote($api['match'])."([/\?#]|$)>"; if ($url === $api['match'] || in_array(substr($api['match'], -1, 1), ["/", "?", "#"]) || preg_match($pattern, $url)) { @@ -200,7 +199,7 @@ class REST { if ($req->hasHeader("Access-Control-Request-Headers")) { $res = $res->withHeader("Access-Control-Allow-Headers", $req->getHeaderLine("Access-Control-Request-Headers")); } - $res = $res->withHeader("Access-Control-Max-Age", (string) (60 *60 *24)); // one day + $res = $res->withHeader("Access-Control-Max-Age", (string) (60 * 60 * 24)); // one day } $res = $res->withHeader("Access-Control-Allow-Origin", $req->getHeaderLine("Origin")); $res = $res->withHeader("Access-Control-Allow-Credentials", "true"); diff --git a/lib/REST/Fever/API.php b/lib/REST/Fever/API.php index 776490c..ac6bb67 100644 --- a/lib/REST/Fever/API.php +++ b/lib/REST/Fever/API.php @@ -67,7 +67,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { switch ($req->getMethod()) { case "OPTIONS": return new EmptyResponse(204, [ - 'Allow' => "POST", + 'Allow' => "POST", 'Accept' => self::ACCEPTED_TYPE, ]); case "POST": @@ -76,7 +76,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { } $out = [ 'api_version' => self::LEVEL, - 'auth' => 0, + 'auth' => 0, ]; if ($req->getAttribute("authenticated", false)) { // if HTTP authentication was successfully used, set the expected user ID @@ -153,7 +153,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { // we provide a single blank favicon for now $out['favicons'] = [ [ - 'id' => 0, + 'id' => 0, 'data' => self::GENERIC_ICON_TYPE.",".self::GENERIC_ICON_DATA, ], ]; @@ -178,7 +178,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { protected function baseResponse(bool $authenticated): array { $out = [ 'api_version' => self::LEVEL, - 'auth' => (int) $authenticated, + 'auth' => (int) $authenticated, ]; if ($authenticated) { // authenticated requests always include the most recent feed refresh @@ -346,7 +346,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { $out = []; foreach (Arsse::$db->tagList(Arsse::$user->id) as $member) { $out[] = [ - 'id' => (int) $member['id'], + 'id' => (int) $member['id'], 'title' => $member['name'], ]; } diff --git a/lib/REST/NextcloudNews/V1_2.php b/lib/REST/NextcloudNews/V1_2.php index 90e7009..6e1fb27 100644 --- a/lib/REST/NextcloudNews/V1_2.php +++ b/lib/REST/NextcloudNews/V1_2.php @@ -215,7 +215,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { return $feed; } - protected function articleTranslate(array $article) :array { + protected function articleTranslate(array $article): array { // map fields to proper names $article = $this->fieldMapNames($article, [ 'id' => "edition", @@ -616,7 +616,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { $c = new Context; $c->article((int) $url[2]); // determine whether to mark read or unread - $set = ($url[3] ==="star"); + $set = ($url[3] === "star"); try { Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c); } catch (ExceptionInput $e) { @@ -629,7 +629,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // mark an array of articles as read protected function articleMarkReadMulti(array $url, array $data): ResponseInterface { // determine whether to mark read or unread - $set = ($url[1] ==="read"); + $set = ($url[1] === "read"); // initialize the matching context $c = new Context; $c->editions($data['items'] ?? []); @@ -643,7 +643,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // mark an array of articles as starred protected function articleMarkStarredMulti(array $url, array $data): ResponseInterface { // determine whether to mark starred or unstarred - $set = ($url[1] ==="star"); + $set = ($url[1] === "star"); // initialize the matching context $c = new Context; $c->articles(array_column($data['items'] ?? [], "guidHash")); @@ -656,10 +656,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { protected function userStatus(array $url, array $data): ResponseInterface { return new Response([ - 'userId' => (string) Arsse::$user->id, - 'displayName' => (string) Arsse::$user->id, + 'userId' => (string) Arsse::$user->id, + 'displayName' => (string) Arsse::$user->id, 'lastLoginTimestamp' => time(), - 'avatar' => null, + 'avatar' => null, ]); } @@ -676,19 +676,19 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { // return the server version protected function serverVersion(array $url, array $data): ResponseInterface { return new Response([ - 'version' => self::VERSION, + 'version' => self::VERSION, 'arsse_version' => Arsse::VERSION, ]); } protected function serverStatus(array $url, array $data): ResponseInterface { return new Response([ - 'version' => self::VERSION, + 'version' => self::VERSION, 'arsse_version' => Arsse::VERSION, - 'warnings' => [ + 'warnings' => [ 'improperlyConfiguredCron' => !Service::hasCheckedIn(), - 'incorrectDbCharset' => !Arsse::$db->driverCharsetAcceptable(), - ] + 'incorrectDbCharset' => !Arsse::$db->driverCharsetAcceptable(), + ], ]); } } diff --git a/lib/REST/NextcloudNews/Versions.php b/lib/REST/NextcloudNews/Versions.php index a8db7a7..8337736 100644 --- a/lib/REST/NextcloudNews/Versions.php +++ b/lib/REST/NextcloudNews/Versions.php @@ -29,7 +29,7 @@ class Versions implements \JKingWeb\Arsse\REST\Handler { $out = [ 'apiLevels' => [ 'v1-2', - ] + ], ]; return new Response($out); default: diff --git a/lib/REST/TinyTinyRSS/API.php b/lib/REST/TinyTinyRSS/API.php index 4049a2a..d0df548 100644 --- a/lib/REST/TinyTinyRSS/API.php +++ b/lib/REST/TinyTinyRSS/API.php @@ -135,14 +135,14 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { throw new Exception("UNKNOWN_METHOD", ['method' => $data['op']]); } return new Response([ - 'seq' => $data['seq'], - 'status' => 0, + 'seq' => $data['seq'], + 'status' => 0, 'content' => $this->$method($data), ]); } catch (Exception $e) { return new Response([ - 'seq' => $data['seq'], - 'status' => 1, + 'seq' => $data['seq'], + 'status' => 1, 'content' => $e->getData(), ]); } catch (AbstractException $e) { @@ -190,7 +190,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { // are not enforced, create a session for the HTTP user regardless // of which user the API call mentions $id = Arsse::$db->sessionCreate(Arsse::$user->id); - } elseif ((!Arsse::$conf->userPreAuth && (Arsse::$user->auth($user, $pass) || Arsse::$user->auth($user, base64_decode($pass)))) || (Arsse::$conf->userPreAuth && Arsse::$user->id===$user)) { + } elseif ((!Arsse::$conf->userPreAuth && (Arsse::$user->auth($user, $pass) || Arsse::$user->auth($user, base64_decode($pass)))) || (Arsse::$conf->userPreAuth && Arsse::$user->id === $user)) { // otherwise both cleartext and base64 passwords are accepted // if pre-authentication is in use, just make sure the user names match $id = Arsse::$db->sessionCreate($user); @@ -199,7 +199,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { } return [ 'session_id' => $id, - 'api_level' => self::LEVEL + 'api_level' => self::LEVEL, ]; } @@ -215,10 +215,10 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { public function opGetConfig(array $data): array { return [ - 'icons_dir' => "feed-icons", - 'icons_url' => "feed-icons", + 'icons_dir' => "feed-icons", + 'icons_url' => "feed-icons", 'daemon_is_running' => Service::hasCheckedIn(), - 'num_feeds' => Arsse::$db->subscriptionCount(Arsse::$user->id), + 'num_feeds' => Arsse::$db->subscriptionCount(Arsse::$user->id), ]; } @@ -304,7 +304,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { return array_merge($special, $labels, $feeds, $cats); } - public function opGetFeedTree(array $data) : array { + public function opGetFeedTree(array $data): array { $all = $data['include_empty'] ?? false; $user = Arsse::$user->id; $tSpecial = [ @@ -319,55 +319,55 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { $subs = Arsse::$db->subscriptionList($user)->getAll(); // start with the special feeds $out[] = [ - 'name' => Arsse::$lang->msg("API.TTRSS.Category.Special"), - 'id' => "CAT:".self::CAT_SPECIAL, + 'name' => Arsse::$lang->msg("API.TTRSS.Category.Special"), + 'id' => "CAT:".self::CAT_SPECIAL, 'bare_id' => self::CAT_SPECIAL, - 'type' => "category", - 'unread' => 0, - 'items' => [ + 'type' => "category", + 'unread' => 0, + 'items' => [ array_merge([ // All articles - 'name' => Arsse::$lang->msg("API.TTRSS.Feed.All"), - 'id' => "FEED:".self::FEED_ALL, + 'name' => Arsse::$lang->msg("API.TTRSS.Feed.All"), + 'id' => "FEED:".self::FEED_ALL, 'bare_id' => self::FEED_ALL, - 'icon' => "images/folder.png", - 'unread' => array_reduce($subs, function($sum, $value) { + 'icon' => "images/folder.png", + 'unread' => array_reduce($subs, function($sum, $value) { return $sum + $value['unread']; }, 0), // the sum of all feeds' unread is the total unread ], $tSpecial), array_merge([ // Fresh articles - 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Fresh"), - 'id' => "FEED:".self::FEED_FRESH, + 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Fresh"), + 'id' => "FEED:".self::FEED_FRESH, 'bare_id' => self::FEED_FRESH, - 'icon' => "images/fresh.png", - 'unread' => Arsse::$db->articleCount($user, (new Context)->unread(true)->modifiedSince(Date::sub("PT24H"))), + 'icon' => "images/fresh.png", + 'unread' => Arsse::$db->articleCount($user, (new Context)->unread(true)->modifiedSince(Date::sub("PT24H"))), ], $tSpecial), array_merge([ // Starred articles - 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Starred"), - 'id' => "FEED:".self::FEED_STARRED, + 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Starred"), + 'id' => "FEED:".self::FEED_STARRED, 'bare_id' => self::FEED_STARRED, - 'icon' => "images/star.png", - 'unread' => (int) Arsse::$db->articleStarred($user)['unread'], + 'icon' => "images/star.png", + 'unread' => (int) Arsse::$db->articleStarred($user)['unread'], ], $tSpecial), array_merge([ // Published articles - 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Published"), - 'id' => "FEED:".self::FEED_PUBLISHED, + 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Published"), + 'id' => "FEED:".self::FEED_PUBLISHED, 'bare_id' => self::FEED_PUBLISHED, - 'icon' => "images/feed.png", - 'unread' => 0, // TODO: unread count should be populated if the Published feed is ever implemented + 'icon' => "images/feed.png", + 'unread' => 0, // TODO: unread count should be populated if the Published feed is ever implemented ], $tSpecial), array_merge([ // Archived articles - 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Archived"), - 'id' => "FEED:".self::FEED_ARCHIVED, + 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Archived"), + 'id' => "FEED:".self::FEED_ARCHIVED, 'bare_id' => self::FEED_ARCHIVED, - 'icon' => "images/archive.png", - 'unread' => 0, // Article archiving is not exposed by the API, so this is always zero + 'icon' => "images/archive.png", + 'unread' => 0, // Article archiving is not exposed by the API, so this is always zero ], $tSpecial), array_merge([ // Recently read - 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Read"), - 'id' => "FEED:".self::FEED_READ, + 'name' => Arsse::$lang->msg("API.TTRSS.Feed.Read"), + 'id' => "FEED:".self::FEED_READ, 'bare_id' => self::FEED_READ, - 'icon' => "images/time.png", - 'unread' => 0, // this is by definition zero; unread articles do not appear in this feed + 'icon' => "images/time.png", + 'unread' => 0, // this is by definition zero; unread articles do not appear in this feed ], $tSpecial), ], ]; @@ -394,12 +394,12 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { // if there are labels, all the label category, if ($items) { $out[] = [ - 'name' => Arsse::$lang->msg("API.TTRSS.Category.Labels"), - 'id' => "CAT:".self::CAT_LABELS, + 'name' => Arsse::$lang->msg("API.TTRSS.Category.Labels"), + 'id' => "CAT:".self::CAT_LABELS, 'bare_id' => self::CAT_LABELS, - 'type' => "category", - 'unread' => $unread, - 'items' => $items, + 'type' => "category", + 'unread' => $unread, + 'items' => $items, ]; } // get the lists of categories and feeds @@ -459,7 +459,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { // if the category is the wrong level, or if it's empty and we're not including empties, skip it continue; } - $children = $c['children'] ? $this->enumerateCategories($cats, $subs, $c['id'], $all) : ['list' => [], 'feeds' => 0]; + $children = $c['children'] ? $this->enumerateCategories($cats, $subs, $c['id'], $all) : ['list' => [], 'feeds' => 0]; $feeds = $c['feeds'] ? $this->enumerateFeeds($subs, $c['id']) : []; $count = sizeof($feeds) + (int) $children['feeds']; $out[] = [ @@ -843,7 +843,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { $subs = Arsse::$db->subscriptionList(Arsse::$user->id); $id = false; foreach ($subs as $sub) { - if ($sub['url']===$url) { + if ($sub['url'] === $url) { $id = (int) $sub['id']; break; } @@ -940,11 +940,11 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { return 0; } } - return (abs($id) - self::LABEL_OFFSET); + return abs($id) - self::LABEL_OFFSET; } protected function labelOut($id): int { - return ((int) $id * -1 - self::LABEL_OFFSET); + return (int) $id * -1 - self::LABEL_OFFSET; } public function opGetLabels(array $data): array { @@ -1201,32 +1201,32 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { ]; foreach (Arsse::$db->articleList(Arsse::$user->id, (new Context)->articles($articles), $columns) as $article) { $out[] = [ - 'id' => (string) $article['id'], // string cast to be consistent with TTRSS - 'guid' => $article['guid'] ? "SHA256:".$article['guid'] : null, - 'title' => $article['title'], - 'link' => $article['url'], - 'labels' => $this->articleLabelList($labels, $article['id']), - 'unread' => (bool) $article['unread'], - 'marked' => (bool) $article['starred'], - 'published' => false, // TODO: if the Published feed is implemented, the getArticle operation should be amended accordingly - 'comments' => "", // FIXME: What is this? - 'author' => $article['author'], - 'updated' => Date::transform($article['edited_date'], "unix", "sql"), - 'feed_id' => (string) $article['subscription'], // string cast to be consistent with TTRSS - 'feed_title' => $article['subscription_title'], + 'id' => (string) $article['id'], // string cast to be consistent with TTRSS + 'guid' => $article['guid'] ? "SHA256:".$article['guid'] : null, + 'title' => $article['title'], + 'link' => $article['url'], + 'labels' => $this->articleLabelList($labels, $article['id']), + 'unread' => (bool) $article['unread'], + 'marked' => (bool) $article['starred'], + 'published' => false, // TODO: if the Published feed is implemented, the getArticle operation should be amended accordingly + 'comments' => "", // FIXME: What is this? + 'author' => $article['author'], + 'updated' => Date::transform($article['edited_date'], "unix", "sql"), + 'feed_id' => (string) $article['subscription'], // string cast to be consistent with TTRSS + 'feed_title' => $article['subscription_title'], 'attachments' => $article['media_url'] ? [[ - 'id' => (string) 0, // string cast to be consistent with TTRSS; nonsense ID because we don't use them for enclosures - 'content_url' => $article['media_url'], + 'id' => (string) 0, // string cast to be consistent with TTRSS; nonsense ID because we don't use them for enclosures + 'content_url' => $article['media_url'], 'content_type' => $article['media_type'], - 'title' => "", - 'duration' => "", - 'width' => "", - 'height' => "", - 'post_id' => (string) $article['id'], // string cast to be consistent with TTRSS + 'title' => "", + 'duration' => "", + 'width' => "", + 'height' => "", + 'post_id' => (string) $article['id'], // string cast to be consistent with TTRSS ]] : [], // TODO: We need to support multiple enclosures - 'score' => 0, // score is not implemented as it is not modifiable from the TTRSS API - 'note' => strlen((string) $article['note']) ? $article['note'] : null, - 'lang' => "", // FIXME: picoFeed should be able to retrieve this information + 'score' => 0, // score is not implemented as it is not modifiable from the TTRSS API + 'note' => strlen((string) $article['note']) ? $article['note'] : null, + 'lang' => "", // FIXME: picoFeed should be able to retrieve this information 'content' => $article['content'], ]; } @@ -1302,25 +1302,25 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { ]; foreach ($this->fetchArticles($data, $columns) as $article) { $row = [ - 'id' => (int) $article['id'], - 'guid' => $article['guid'] ? "SHA256:".$article['guid'] : "", - 'title' => $article['title'], - 'link' => $article['url'], - 'labels' => $this->articleLabelList($labels, $article['id']), - 'unread' => (bool) $article['unread'], - 'marked' => (bool) $article['starred'], - 'published' => false, // TODO: if the Published feed is implemented, the getHeadlines operation should be amended accordingly - 'author' => $article['author'], - 'updated' => Date::transform($article['edited_date'], "unix", "sql"), - 'is_updated' => ($article['published_date'] < $article['edited_date']), - 'feed_id' => (string) $article['subscription'], // string cast to be consistent with TTRSS - 'feed_title' => $article['subscription_title'], - 'score' => 0, // score is not implemented as it is not modifiable from the TTRSS API - 'note' => strlen((string) $article['note']) ? $article['note'] : null, - 'lang' => "", // FIXME: picoFeed should be able to retrieve this information - 'tags' => Arsse::$db->articleCategoriesGet(Arsse::$user->id, $article['id']), - 'comments_count' => 0, - 'comments_link' => "", + 'id' => (int) $article['id'], + 'guid' => $article['guid'] ? "SHA256:".$article['guid'] : "", + 'title' => $article['title'], + 'link' => $article['url'], + 'labels' => $this->articleLabelList($labels, $article['id']), + 'unread' => (bool) $article['unread'], + 'marked' => (bool) $article['starred'], + 'published' => false, // TODO: if the Published feed is implemented, the getHeadlines operation should be amended accordingly + 'author' => $article['author'], + 'updated' => Date::transform($article['edited_date'], "unix", "sql"), + 'is_updated' => ($article['published_date'] < $article['edited_date']), + 'feed_id' => (string) $article['subscription'], // string cast to be consistent with TTRSS + 'feed_title' => $article['subscription_title'], + 'score' => 0, // score is not implemented as it is not modifiable from the TTRSS API + 'note' => strlen((string) $article['note']) ? $article['note'] : null, + 'lang' => "", // FIXME: picoFeed should be able to retrieve this information + 'tags' => Arsse::$db->articleCategoriesGet(Arsse::$user->id, $article['id']), + 'comments_count' => 0, + 'comments_link' => "", 'always_display_attachments' => false, ]; if ($data['show_content']) { @@ -1336,14 +1336,14 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { } if ($data['include_attachments']) { $row['attachments'] = $article['media_url'] ? [[ - 'id' => (string) 0, // string cast to be consistent with TTRSS; nonsense ID because we don't use them for enclosures - 'content_url' => $article['media_url'], + 'id' => (string) 0, // string cast to be consistent with TTRSS; nonsense ID because we don't use them for enclosures + 'content_url' => $article['media_url'], 'content_type' => $article['media_type'], - 'title' => "", - 'duration' => "", - 'width' => "", - 'height' => "", - 'post_id' => (string) $article['id'], // string cast to be consistent with TTRSS + 'title' => "", + 'duration' => "", + 'width' => "", + 'height' => "", + 'post_id' => (string) $article['id'], // string cast to be consistent with TTRSS ]] : []; // TODO: We need to support multiple enclosures } $out[] = $row; diff --git a/lib/Service.php b/lib/Service.php index ed234d6..fc77e80 100644 --- a/lib/Service.php +++ b/lib/Service.php @@ -66,7 +66,7 @@ class Service { $limit->sub($int); $limit->sub($int); // return whether the check-in time is within the acceptable limit - return ($checkin >= $limit); + return $checkin >= $limit; } public static function cleanupPre(): bool { diff --git a/lib/User.php b/lib/User.php index 713f17c..15d902c 100644 --- a/lib/User.php +++ b/lib/User.php @@ -15,9 +15,7 @@ class User { public $id = null; - /** - * @var User\Driver - */ + /** @var User\Driver */ protected $u; public function __construct(\JKingWeb\Arsse\User\Driver $driver = null) { diff --git a/lib/User/Internal/Driver.php b/lib/User/Internal/Driver.php index c9e78d1..4fc787f 100644 --- a/lib/User/Internal/Driver.php +++ b/lib/User/Internal/Driver.php @@ -26,7 +26,7 @@ class Driver implements \JKingWeb\Arsse\User\Driver { } catch (Exception $e) { return false; } - if ($password==="" && $hash==="") { + if ($password === "" && $hash === "") { return true; } return password_verify($password, $hash); diff --git a/tests/cases/CLI/TestCLI.php b/tests/cases/CLI/TestCLI.php index ef302f2..e6c19e2 100644 --- a/tests/cases/CLI/TestCLI.php +++ b/tests/cases/CLI/TestCLI.php @@ -163,10 +163,10 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { // FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead Arsse::$user = $this->createMock(User::class); Arsse::$user->method("auth")->will($this->returnCallback(function($user, $pass) { - return ( + return ($user === "john.doe@example.com" && $pass === "secret") || ($user === "jane.doe@example.com" && $pass === "superman") - ); + ; })); $fever = \Phake::mock(FeverUser::class); \Phake::when($fever)->authenticate->thenReturn(false); diff --git a/tests/cases/Conf/TestConf.php b/tests/cases/Conf/TestConf.php index 6728333..e99eda3 100644 --- a/tests/cases/Conf/TestConf.php +++ b/tests/cases/Conf/TestConf.php @@ -45,7 +45,7 @@ class TestConf extends \JKingWeb\Arsse\Test\AbstractTest { /** @depends testLoadDefaultValues */ public function testImportFromArray(): void { $arr = [ - 'lang' => "xx", + 'lang' => "xx", 'purgeFeeds' => "P2D", ]; $conf = new Conf; @@ -125,9 +125,9 @@ class TestConf extends \JKingWeb\Arsse\Test\AbstractTest { $conf->serviceFrequency = new \DateInterval("PT1H"); // should be exported (as string): value changed $conf->someCustomProperty = "Look at me!"; // should be exported: unknown property $exp = [ - 'dbSQLite3File' => "test.db", - 'userDriver' => null, - 'serviceFrequency' => "PT1H", + 'dbSQLite3File' => "test.db", + 'userDriver' => null, + 'serviceFrequency' => "PT1H", 'someCustomProperty' => "Look at me!", ]; $this->assertSame($exp, $conf->export()); @@ -147,8 +147,8 @@ class TestConf extends \JKingWeb\Arsse\Test\AbstractTest { $conf->exportFile(self::$path."confNotArray"); $arr = (include self::$path."confNotArray"); $exp = [ - 'dbSQLite3File' => "test.db", - 'userDriver' => null, + 'dbSQLite3File' => "test.db", + 'userDriver' => null, 'someCustomProperty' => "Look at me!", ]; $this->assertSame($exp, $arr); diff --git a/tests/cases/Database/SeriesArticle.php b/tests/cases/Database/SeriesArticle.php index 13a5e93..d268d2a 100644 --- a/tests/cases/Database/SeriesArticle.php +++ b/tests/cases/Database/SeriesArticle.php @@ -47,7 +47,7 @@ trait SeriesArticle { [11,"http://example.com/11", "Feed 11"], [12,"http://example.com/12", "Feed 12"], [13,"http://example.com/13", "Feed 13"], - ] + ], ], 'arsse_folders' => [ 'columns' => [ @@ -66,7 +66,7 @@ trait SeriesArticle { [7, "john.doe@example.net", null, "Technology"], [8, "john.doe@example.net", 7, "Software"], [9, "john.doe@example.net", null, "Politics"], - ] + ], ], 'arsse_tags' => [ 'columns' => [ @@ -83,7 +83,7 @@ trait SeriesArticle { [6, "john.doe@example.net", "Technology"], [7, "john.doe@example.net", "Software"], [8, "john.doe@example.net", "Politics"], - ] + ], ], 'arsse_subscriptions' => [ 'columns' => [ @@ -108,7 +108,7 @@ trait SeriesArticle { [12,"john.doe@example.net",2, 9,null], [13,"john.doe@example.net",3, 8,"Subscription 13"], [14,"john.doe@example.net",4, 7,null], - ] + ], ], 'arsse_tag_members' => [ 'columns' => [ @@ -171,7 +171,7 @@ trait SeriesArticle { [103,12,'http://example.com/3','Article title 3','','2000-01-03 00:00:00','2000-01-03 00:00:03','

Article content 3

','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b','2000-01-03 03:00:00'], [104,12,'http://example.com/4','Article title 4','','2000-01-04 00:00:00','2000-01-04 00:00:04','

Article content 4

','804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8','f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3','ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9','2000-01-04 04:00:00'], [105,13,'http://example.com/5','Article title 5','','2000-01-05 00:00:00','2000-01-05 00:00:05','

Article content 5

','db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41','d40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022','834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900','43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba','2000-01-05 05:00:00'], - ] + ], ], 'arsse_enclosures' => [ 'columns' => [ @@ -185,7 +185,7 @@ trait SeriesArticle { [104,"http://example.com/image","image/svg+xml"], [105,"http://example.com/audio","audio/ogg"], - ] + ], ], 'arsse_editions' => [ 'columns' => [ @@ -224,7 +224,7 @@ trait SeriesArticle { [205,105], [305,105], [1001,20], - ] + ], ], 'arsse_marks' => [ 'columns' => [ @@ -249,7 +249,7 @@ trait SeriesArticle { [12, 3,0,1,'2017-01-01 00:00:00','ack'], [12, 4,1,1,'2017-01-01 00:00:00','ach'], [1, 2,0,0,'2010-01-01 00:00:00','Some Note'], - ] + ], ], 'arsse_categories' => [ // author-supplied categories 'columns' => [ @@ -298,104 +298,104 @@ trait SeriesArticle { ]; $this->matches = [ [ - 'id' => 101, - 'url' => 'http://example.com/1', - 'title' => 'Article title 1', + 'id' => 101, + 'url' => 'http://example.com/1', + 'title' => 'Article title 1', 'subscription_title' => "Feed 11", - 'author' => '', - 'content' => '

Article content 1

', - 'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda', - 'published_date' => '2000-01-01 00:00:00', - 'edited_date' => '2000-01-01 00:00:01', - 'modified_date' => '2000-01-01 01:00:00', - 'unread' => 1, - 'starred' => 0, - 'edition' => 101, - 'subscription' => 8, - 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', - 'media_url' => null, - 'media_type' => null, - 'note' => "", + 'author' => '', + 'content' => '

Article content 1

', + 'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda', + 'published_date' => '2000-01-01 00:00:00', + 'edited_date' => '2000-01-01 00:00:01', + 'modified_date' => '2000-01-01 01:00:00', + 'unread' => 1, + 'starred' => 0, + 'edition' => 101, + 'subscription' => 8, + 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', + 'media_url' => null, + 'media_type' => null, + 'note' => "", ], [ - 'id' => 102, - 'url' => 'http://example.com/2', - 'title' => 'Article title 2', + 'id' => 102, + 'url' => 'http://example.com/2', + 'title' => 'Article title 2', 'subscription_title' => "Feed 11", - 'author' => '', - 'content' => '

Article content 2

', - 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', - 'published_date' => '2000-01-02 00:00:00', - 'edited_date' => '2000-01-02 00:00:02', - 'modified_date' => '2000-01-02 02:00:00', - 'unread' => 0, - 'starred' => 0, - 'edition' => 202, - 'subscription' => 8, - 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', - 'media_url' => "http://example.com/text", - 'media_type' => "text/plain", - 'note' => "Note 2", + 'author' => '', + 'content' => '

Article content 2

', + 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', + 'published_date' => '2000-01-02 00:00:00', + 'edited_date' => '2000-01-02 00:00:02', + 'modified_date' => '2000-01-02 02:00:00', + 'unread' => 0, + 'starred' => 0, + 'edition' => 202, + 'subscription' => 8, + 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', + 'media_url' => "http://example.com/text", + 'media_type' => "text/plain", + 'note' => "Note 2", ], [ - 'id' => 103, - 'url' => 'http://example.com/3', - 'title' => 'Article title 3', + 'id' => 103, + 'url' => 'http://example.com/3', + 'title' => 'Article title 3', 'subscription_title' => "Subscription 9", - 'author' => '', - 'content' => '

Article content 3

', - 'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92', - 'published_date' => '2000-01-03 00:00:00', - 'edited_date' => '2000-01-03 00:00:03', - 'modified_date' => '2000-01-03 03:00:00', - 'unread' => 1, - 'starred' => 1, - 'edition' => 203, - 'subscription' => 9, - 'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b', - 'media_url' => "http://example.com/video", - 'media_type' => "video/webm", - 'note' => "Note 3", + 'author' => '', + 'content' => '

Article content 3

', + 'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92', + 'published_date' => '2000-01-03 00:00:00', + 'edited_date' => '2000-01-03 00:00:03', + 'modified_date' => '2000-01-03 03:00:00', + 'unread' => 1, + 'starred' => 1, + 'edition' => 203, + 'subscription' => 9, + 'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b', + 'media_url' => "http://example.com/video", + 'media_type' => "video/webm", + 'note' => "Note 3", ], [ - 'id' => 104, - 'url' => 'http://example.com/4', - 'title' => 'Article title 4', + 'id' => 104, + 'url' => 'http://example.com/4', + 'title' => 'Article title 4', 'subscription_title' => "Subscription 9", - 'author' => '', - 'content' => '

Article content 4

', - 'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180', - 'published_date' => '2000-01-04 00:00:00', - 'edited_date' => '2000-01-04 00:00:04', - 'modified_date' => '2000-01-04 04:00:00', - 'unread' => 0, - 'starred' => 1, - 'edition' => 204, - 'subscription' => 9, - 'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9', - 'media_url' => "http://example.com/image", - 'media_type' => "image/svg+xml", - 'note' => "Note 4", + 'author' => '', + 'content' => '

Article content 4

', + 'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180', + 'published_date' => '2000-01-04 00:00:00', + 'edited_date' => '2000-01-04 00:00:04', + 'modified_date' => '2000-01-04 04:00:00', + 'unread' => 0, + 'starred' => 1, + 'edition' => 204, + 'subscription' => 9, + 'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9', + 'media_url' => "http://example.com/image", + 'media_type' => "image/svg+xml", + 'note' => "Note 4", ], [ - 'id' => 105, - 'url' => 'http://example.com/5', - 'title' => 'Article title 5', + 'id' => 105, + 'url' => 'http://example.com/5', + 'title' => 'Article title 5', 'subscription_title' => "Feed 13", - 'author' => '', - 'content' => '

Article content 5

', - 'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41', - 'published_date' => '2000-01-05 00:00:00', - 'edited_date' => '2000-01-05 00:00:05', - 'modified_date' => '2000-01-05 05:00:00', - 'unread' => 1, - 'starred' => 0, - 'edition' => 305, - 'subscription' => 10, - 'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba', - 'media_url' => "http://example.com/audio", - 'media_type' => "audio/ogg", - 'note' => "", + 'author' => '', + 'content' => '

Article content 5

', + 'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41', + 'published_date' => '2000-01-05 00:00:00', + 'edited_date' => '2000-01-05 00:00:05', + 'modified_date' => '2000-01-05 05:00:00', + 'unread' => 1, + 'starred' => 0, + 'edition' => 305, + 'subscription' => 10, + 'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba', + 'media_url' => "http://example.com/audio", + 'media_type' => "audio/ogg", + 'note' => "", ], ]; $this->fields = [ @@ -404,7 +404,7 @@ trait SeriesArticle { "content", "media_url", "media_type", "note", ]; - $this->checkTables = ['arsse_marks' => ["subscription","article","read","starred","modified","note"],]; + $this->checkTables = ['arsse_marks' => ["subscription","article","read","starred","modified","note"]]; $this->user = "john.doe@example.net"; } @@ -422,132 +422,132 @@ trait SeriesArticle { public function provideContextMatches(): iterable { return [ - 'Blank context' => [new Context, [1,2,3,4,5,6,7,8,19,20]], - 'Folder tree' => [(new Context)->folder(1), [5,6,7,8]], - 'Entire folder tree' => [(new Context)->folder(0), [1,2,3,4,5,6,7,8,19,20]], - 'Leaf folder' => [(new Context)->folder(6), [7,8]], - 'Multiple folder trees' => [(new Context)->folders([1,5]), [5,6,7,8,19,20]], - 'Multiple folder trees including root' => [(new Context)->folders([0,1,5]), [1,2,3,4,5,6,7,8,19,20]], - 'Shallow folder' => [(new Context)->folderShallow(1), [5,6]], - 'Root folder only' => [(new Context)->folderShallow(0), [1,2,3,4]], - 'Multiple shallow folders' => [(new Context)->foldersShallow([1,6]), [5,6,7,8]], - 'Subscription' => [(new Context)->subscription(5), [19,20]], - 'Multiple subscriptions' => [(new Context)->subscriptions([4,5]), [7,8,19,20]], - 'Unread' => [(new Context)->subscription(5)->unread(true), [20]], - 'Read' => [(new Context)->subscription(5)->unread(false), [19]], - 'Starred' => [(new Context)->starred(true), [1,20]], - 'Unstarred' => [(new Context)->starred(false), [2,3,4,5,6,7,8,19]], - 'Starred and Read' => [(new Context)->starred(true)->unread(false), [1]], - 'Starred and Read in subscription' => [(new Context)->starred(true)->unread(false)->subscription(5), []], - 'Annotated' => [(new Context)->annotated(true), [2]], - 'Not annotated' => [(new Context)->annotated(false), [1,3,4,5,6,7,8,19,20]], - 'Labelled' => [(new Context)->labelled(true), [1,5,8,19,20]], - 'Not labelled' => [(new Context)->labelled(false), [2,3,4,6,7]], - 'Not after edition 999' => [(new Context)->subscription(5)->latestEdition(999), [19]], - 'Not after edition 19' => [(new Context)->subscription(5)->latestEdition(19), [19]], - 'Not before edition 999' => [(new Context)->subscription(5)->oldestEdition(999), [20]], - 'Not before edition 1001' => [(new Context)->subscription(5)->oldestEdition(1001), [20]], - 'Not after article 3' => [(new Context)->latestArticle(3), [1,2,3]], - 'Not before article 19' => [(new Context)->oldestArticle(19), [19,20]], - 'Modified by author since 2005' => [(new Context)->modifiedSince("2005-01-01T00:00:00Z"), [2,4,6,8,20]], - 'Modified by author since 2010' => [(new Context)->modifiedSince("2010-01-01T00:00:00Z"), [2,4,6,8,20]], - 'Not modified by author since 2005' => [(new Context)->notModifiedSince("2005-01-01T00:00:00Z"), [1,3,5,7,19]], - 'Not modified by author since 2000' => [(new Context)->notModifiedSince("2000-01-01T00:00:00Z"), [1,3,5,7,19]], - 'Marked or labelled since 2014' => [(new Context)->markedSince("2014-01-01T00:00:00Z"), [8,19]], - 'Marked or labelled since 2010' => [(new Context)->markedSince("2010-01-01T00:00:00Z"), [2,4,6,8,19,20]], - 'Not marked or labelled since 2014' => [(new Context)->notMarkedSince("2014-01-01T00:00:00Z"), [1,2,3,4,5,6,7,20]], - 'Not marked or labelled since 2005' => [(new Context)->notMarkedSince("2005-01-01T00:00:00Z"), [1,3,5,7]], - 'Marked or labelled between 2000 and 2015' => [(new Context)->markedSince("2000-01-01T00:00:00Z")->notMarkedSince("2015-12-31T23:59:59Z"), [1,2,3,4,5,6,7,8,20]], - 'Marked or labelled in 2010' => [(new Context)->markedSince("2010-01-01T00:00:00Z")->notMarkedSince("2010-12-31T23:59:59Z"), [2,4,6,20]], - 'Paged results' => [(new Context)->limit(2)->oldestEdition(4), [4,5]], - 'With label ID 1' => [(new Context)->label(1), [1,19]], - 'With label ID 2' => [(new Context)->label(2), [1,5,20]], - 'With label ID 1 or 2' => [(new Context)->labels([1,2]), [1,5,19,20]], - 'With label "Interesting"' => [(new Context)->labelName("Interesting"), [1,19]], - 'With label "Fascinating"' => [(new Context)->labelName("Fascinating"), [1,5,20]], - 'With label "Interesting" or "Fascinating"' => [(new Context)->labelNames(["Interesting","Fascinating"]), [1,5,19,20]], - 'Article ID 20' => [(new Context)->article(20), [20]], - 'Edition ID 1001' => [(new Context)->edition(1001), [20]], - 'Multiple articles' => [(new Context)->articles([1,20,50]), [1,20]], - 'Multiple starred articles' => [(new Context)->articles([1,2,3])->starred(true), [1]], - 'Multiple unstarred articles' => [(new Context)->articles([1,2,3])->starred(false), [2,3]], - 'Multiple articles' => [(new Context)->articles([1,20,50]), [1,20]], - 'Multiple editions' => [(new Context)->editions([1,1001,50]), [1,20]], - '150 articles' => [(new Context)->articles(range(1, Database::LIMIT_SET_SIZE * 3)), [1,2,3,4,5,6,7,8,19,20]], - 'Search title or content 1' => [(new Context)->searchTerms(["Article"]), [1,2,3]], - 'Search title or content 2' => [(new Context)->searchTerms(["one", "first"]), [1]], - 'Search title or content 3' => [(new Context)->searchTerms(["one first"]), []], - 'Search title 1' => [(new Context)->titleTerms(["two"]), [2]], - 'Search title 2' => [(new Context)->titleTerms(["title two"]), [2]], - 'Search title 3' => [(new Context)->titleTerms(["two", "title"]), [2]], - 'Search title 4' => [(new Context)->titleTerms(["two title"]), []], - 'Search note 1' => [(new Context)->annotationTerms(["some"]), [2]], - 'Search note 2' => [(new Context)->annotationTerms(["some Note"]), [2]], - 'Search note 3' => [(new Context)->annotationTerms(["note", "some"]), [2]], - 'Search note 4' => [(new Context)->annotationTerms(["some", "sauce"]), []], - 'Search author 1' => [(new Context)->authorTerms(["doe"]), [4,5,6,7]], - 'Search author 2' => [(new Context)->authorTerms(["jane doe"]), [6,7]], - 'Search author 3' => [(new Context)->authorTerms(["doe", "jane"]), [6,7]], - 'Search author 4' => [(new Context)->authorTerms(["doe jane"]), []], - 'Folder tree 1 excluding subscription 4' => [(new Context)->not->subscription(4)->folder(1), [5,6]], - 'Folder tree 1 excluding articles 7 and 8' => [(new Context)->folder(1)->not->articles([7,8]), [5,6]], - 'Folder tree 1 excluding no articles' => [(new Context)->folder(1)->not->articles([]), [5,6,7,8]], + 'Blank context' => [new Context, [1,2,3,4,5,6,7,8,19,20]], + 'Folder tree' => [(new Context)->folder(1), [5,6,7,8]], + 'Entire folder tree' => [(new Context)->folder(0), [1,2,3,4,5,6,7,8,19,20]], + 'Leaf folder' => [(new Context)->folder(6), [7,8]], + 'Multiple folder trees' => [(new Context)->folders([1,5]), [5,6,7,8,19,20]], + 'Multiple folder trees including root' => [(new Context)->folders([0,1,5]), [1,2,3,4,5,6,7,8,19,20]], + 'Shallow folder' => [(new Context)->folderShallow(1), [5,6]], + 'Root folder only' => [(new Context)->folderShallow(0), [1,2,3,4]], + 'Multiple shallow folders' => [(new Context)->foldersShallow([1,6]), [5,6,7,8]], + 'Subscription' => [(new Context)->subscription(5), [19,20]], + 'Multiple subscriptions' => [(new Context)->subscriptions([4,5]), [7,8,19,20]], + 'Unread' => [(new Context)->subscription(5)->unread(true), [20]], + 'Read' => [(new Context)->subscription(5)->unread(false), [19]], + 'Starred' => [(new Context)->starred(true), [1,20]], + 'Unstarred' => [(new Context)->starred(false), [2,3,4,5,6,7,8,19]], + 'Starred and Read' => [(new Context)->starred(true)->unread(false), [1]], + 'Starred and Read in subscription' => [(new Context)->starred(true)->unread(false)->subscription(5), []], + 'Annotated' => [(new Context)->annotated(true), [2]], + 'Not annotated' => [(new Context)->annotated(false), [1,3,4,5,6,7,8,19,20]], + 'Labelled' => [(new Context)->labelled(true), [1,5,8,19,20]], + 'Not labelled' => [(new Context)->labelled(false), [2,3,4,6,7]], + 'Not after edition 999' => [(new Context)->subscription(5)->latestEdition(999), [19]], + 'Not after edition 19' => [(new Context)->subscription(5)->latestEdition(19), [19]], + 'Not before edition 999' => [(new Context)->subscription(5)->oldestEdition(999), [20]], + 'Not before edition 1001' => [(new Context)->subscription(5)->oldestEdition(1001), [20]], + 'Not after article 3' => [(new Context)->latestArticle(3), [1,2,3]], + 'Not before article 19' => [(new Context)->oldestArticle(19), [19,20]], + 'Modified by author since 2005' => [(new Context)->modifiedSince("2005-01-01T00:00:00Z"), [2,4,6,8,20]], + 'Modified by author since 2010' => [(new Context)->modifiedSince("2010-01-01T00:00:00Z"), [2,4,6,8,20]], + 'Not modified by author since 2005' => [(new Context)->notModifiedSince("2005-01-01T00:00:00Z"), [1,3,5,7,19]], + 'Not modified by author since 2000' => [(new Context)->notModifiedSince("2000-01-01T00:00:00Z"), [1,3,5,7,19]], + 'Marked or labelled since 2014' => [(new Context)->markedSince("2014-01-01T00:00:00Z"), [8,19]], + 'Marked or labelled since 2010' => [(new Context)->markedSince("2010-01-01T00:00:00Z"), [2,4,6,8,19,20]], + 'Not marked or labelled since 2014' => [(new Context)->notMarkedSince("2014-01-01T00:00:00Z"), [1,2,3,4,5,6,7,20]], + 'Not marked or labelled since 2005' => [(new Context)->notMarkedSince("2005-01-01T00:00:00Z"), [1,3,5,7]], + 'Marked or labelled between 2000 and 2015' => [(new Context)->markedSince("2000-01-01T00:00:00Z")->notMarkedSince("2015-12-31T23:59:59Z"), [1,2,3,4,5,6,7,8,20]], + 'Marked or labelled in 2010' => [(new Context)->markedSince("2010-01-01T00:00:00Z")->notMarkedSince("2010-12-31T23:59:59Z"), [2,4,6,20]], + 'Paged results' => [(new Context)->limit(2)->oldestEdition(4), [4,5]], + 'With label ID 1' => [(new Context)->label(1), [1,19]], + 'With label ID 2' => [(new Context)->label(2), [1,5,20]], + 'With label ID 1 or 2' => [(new Context)->labels([1,2]), [1,5,19,20]], + 'With label "Interesting"' => [(new Context)->labelName("Interesting"), [1,19]], + 'With label "Fascinating"' => [(new Context)->labelName("Fascinating"), [1,5,20]], + 'With label "Interesting" or "Fascinating"' => [(new Context)->labelNames(["Interesting","Fascinating"]), [1,5,19,20]], + 'Article ID 20' => [(new Context)->article(20), [20]], + 'Edition ID 1001' => [(new Context)->edition(1001), [20]], + 'Multiple articles' => [(new Context)->articles([1,20,50]), [1,20]], + 'Multiple starred articles' => [(new Context)->articles([1,2,3])->starred(true), [1]], + 'Multiple unstarred articles' => [(new Context)->articles([1,2,3])->starred(false), [2,3]], + 'Multiple articles' => [(new Context)->articles([1,20,50]), [1,20]], + 'Multiple editions' => [(new Context)->editions([1,1001,50]), [1,20]], + '150 articles' => [(new Context)->articles(range(1, Database::LIMIT_SET_SIZE * 3)), [1,2,3,4,5,6,7,8,19,20]], + 'Search title or content 1' => [(new Context)->searchTerms(["Article"]), [1,2,3]], + 'Search title or content 2' => [(new Context)->searchTerms(["one", "first"]), [1]], + 'Search title or content 3' => [(new Context)->searchTerms(["one first"]), []], + 'Search title 1' => [(new Context)->titleTerms(["two"]), [2]], + 'Search title 2' => [(new Context)->titleTerms(["title two"]), [2]], + 'Search title 3' => [(new Context)->titleTerms(["two", "title"]), [2]], + 'Search title 4' => [(new Context)->titleTerms(["two title"]), []], + 'Search note 1' => [(new Context)->annotationTerms(["some"]), [2]], + 'Search note 2' => [(new Context)->annotationTerms(["some Note"]), [2]], + 'Search note 3' => [(new Context)->annotationTerms(["note", "some"]), [2]], + 'Search note 4' => [(new Context)->annotationTerms(["some", "sauce"]), []], + 'Search author 1' => [(new Context)->authorTerms(["doe"]), [4,5,6,7]], + 'Search author 2' => [(new Context)->authorTerms(["jane doe"]), [6,7]], + 'Search author 3' => [(new Context)->authorTerms(["doe", "jane"]), [6,7]], + 'Search author 4' => [(new Context)->authorTerms(["doe jane"]), []], + 'Folder tree 1 excluding subscription 4' => [(new Context)->not->subscription(4)->folder(1), [5,6]], + 'Folder tree 1 excluding articles 7 and 8' => [(new Context)->folder(1)->not->articles([7,8]), [5,6]], + 'Folder tree 1 excluding no articles' => [(new Context)->folder(1)->not->articles([]), [5,6,7,8]], 'Marked or labelled between 2000 and 2015 excluding in 2010' => [(new Context)->markedSince("2000-01-01T00:00:00Z")->notMarkedSince("2015-12-31T23:59:59")->not->markedSince("2010-01-01T00:00:00Z")->not->notMarkedSince("2010-12-31T23:59:59Z"), [1,3,5,7,8]], - 'Search with exclusion' => [(new Context)->searchTerms(["Article"])->not->searchTerms(["one", "two"]), [3]], - 'Excluded folder tree' => [(new Context)->not->folder(1), [1,2,3,4,19,20]], - 'Excluding label ID 2' => [(new Context)->not->label(2), [2,3,4,6,7,8,19]], - 'Excluding label "Fascinating"' => [(new Context)->not->labelName("Fascinating"), [2,3,4,6,7,8,19]], - 'Search 501 terms' => [(new Context)->searchTerms(array_merge(range(1, 500), [str_repeat("a", 1000)])), []], - 'With tag ID 1' => [(new Context)->tag(1), [5,6,7,8]], - 'With tag ID 5' => [(new Context)->tag(5), [7,8,19,20]], - 'With tag ID 1 or 5' => [(new Context)->tags([1,5]), [5,6,7,8,19,20]], - 'With tag "Technology"' => [(new Context)->tagName("Technology"), [5,6,7,8]], - 'With tag "Politics"' => [(new Context)->tagName("Politics"), [7,8,19,20]], - 'With tag "Technology" or "Politics"' => [(new Context)->tagNames(["Technology","Politics"]), [5,6,7,8,19,20]], - 'Excluding tag ID 1' => [(new Context)->not->tag(1), [1,2,3,4,19,20]], - 'Excluding tag ID 5' => [(new Context)->not->tag(5), [1,2,3,4,5,6]], - 'Excluding tag "Technology"' => [(new Context)->not->tagName("Technology"), [1,2,3,4,19,20]], - 'Excluding tag "Politics"' => [(new Context)->not->tagName("Politics"), [1,2,3,4,5,6]], - 'Excluding tags ID 1 and 5' => [(new Context)->not->tags([1,5]), [1,2,3,4]], - 'Excluding tags "Technology" and "Politics"' => [(new Context)->not->tagNames(["Technology","Politics"]), [1,2,3,4]], - 'Excluding entire folder tree' => [(new Context)->not->folder(0), []], - 'Excluding multiple folder trees' => [(new Context)->not->folders([1,5]), [1,2,3,4]], - 'Excluding multiple folder trees including root' => [(new Context)->not->folders([0,1,5]), []], + 'Search with exclusion' => [(new Context)->searchTerms(["Article"])->not->searchTerms(["one", "two"]), [3]], + 'Excluded folder tree' => [(new Context)->not->folder(1), [1,2,3,4,19,20]], + 'Excluding label ID 2' => [(new Context)->not->label(2), [2,3,4,6,7,8,19]], + 'Excluding label "Fascinating"' => [(new Context)->not->labelName("Fascinating"), [2,3,4,6,7,8,19]], + 'Search 501 terms' => [(new Context)->searchTerms(array_merge(range(1, 500), [str_repeat("a", 1000)])), []], + 'With tag ID 1' => [(new Context)->tag(1), [5,6,7,8]], + 'With tag ID 5' => [(new Context)->tag(5), [7,8,19,20]], + 'With tag ID 1 or 5' => [(new Context)->tags([1,5]), [5,6,7,8,19,20]], + 'With tag "Technology"' => [(new Context)->tagName("Technology"), [5,6,7,8]], + 'With tag "Politics"' => [(new Context)->tagName("Politics"), [7,8,19,20]], + 'With tag "Technology" or "Politics"' => [(new Context)->tagNames(["Technology","Politics"]), [5,6,7,8,19,20]], + 'Excluding tag ID 1' => [(new Context)->not->tag(1), [1,2,3,4,19,20]], + 'Excluding tag ID 5' => [(new Context)->not->tag(5), [1,2,3,4,5,6]], + 'Excluding tag "Technology"' => [(new Context)->not->tagName("Technology"), [1,2,3,4,19,20]], + 'Excluding tag "Politics"' => [(new Context)->not->tagName("Politics"), [1,2,3,4,5,6]], + 'Excluding tags ID 1 and 5' => [(new Context)->not->tags([1,5]), [1,2,3,4]], + 'Excluding tags "Technology" and "Politics"' => [(new Context)->not->tagNames(["Technology","Politics"]), [1,2,3,4]], + 'Excluding entire folder tree' => [(new Context)->not->folder(0), []], + 'Excluding multiple folder trees' => [(new Context)->not->folders([1,5]), [1,2,3,4]], + 'Excluding multiple folder trees including root' => [(new Context)->not->folders([0,1,5]), []], ]; } public function testRetrieveArticleIdsForEditions(): void { $exp = [ - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - 10 => 10, - 11 => 11, - 12 => 12, - 13 => 13, - 14 => 14, - 15 => 15, - 16 => 16, - 17 => 17, - 18 => 18, - 19 => 19, - 20 => 20, - 101 => 101, - 102 => 102, - 103 => 103, - 104 => 104, - 105 => 105, - 202 => 102, - 203 => 103, - 204 => 104, - 205 => 105, - 305 => 105, + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, + 6 => 6, + 7 => 7, + 8 => 8, + 9 => 9, + 10 => 10, + 11 => 11, + 12 => 12, + 13 => 13, + 14 => 14, + 15 => 15, + 16 => 16, + 17 => 17, + 18 => 18, + 19 => 19, + 20 => 20, + 101 => 101, + 102 => 102, + 103 => 103, + 104 => 104, + 105 => 105, + 202 => 102, + 203 => 103, + 204 => 104, + 205 => 105, + 305 => 105, 1001 => 20, ]; $this->assertEquals($exp, Arsse::$db->editionArticle(...range(1, 1001))); @@ -606,7 +606,7 @@ trait SeriesArticle { } public function testMarkAllArticlesUnread(): void { - Arsse::$db->articleMark($this->user, ['read'=>false]); + Arsse::$db->articleMark($this->user, ['read' => false]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][9][2] = 0; @@ -617,7 +617,7 @@ trait SeriesArticle { } public function testMarkAllArticlesRead(): void { - Arsse::$db->articleMark($this->user, ['read'=>true]); + Arsse::$db->articleMark($this->user, ['read' => true]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][8][2] = 1; @@ -632,7 +632,7 @@ trait SeriesArticle { } public function testMarkAllArticlesUnstarred(): void { - Arsse::$db->articleMark($this->user, ['starred'=>false]); + Arsse::$db->articleMark($this->user, ['starred' => false]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][10][3] = 0; @@ -643,7 +643,7 @@ trait SeriesArticle { } public function testMarkAllArticlesStarred(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true]); + Arsse::$db->articleMark($this->user, ['starred' => true]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][8][3] = 1; @@ -658,7 +658,7 @@ trait SeriesArticle { } public function testMarkAllArticlesUnreadAndUnstarred(): void { - Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>false]); + Arsse::$db->articleMark($this->user, ['read' => false,'starred' => false]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][9][2] = 0; @@ -672,7 +672,7 @@ trait SeriesArticle { } public function testMarkAllArticlesReadAndStarred(): void { - Arsse::$db->articleMark($this->user, ['read'=>true,'starred'=>true]); + Arsse::$db->articleMark($this->user, ['read' => true,'starred' => true]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][8][2] = 1; @@ -690,7 +690,7 @@ trait SeriesArticle { } public function testMarkAllArticlesUnreadAndStarred(): void { - Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true]); + Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][8][3] = 1; @@ -708,7 +708,7 @@ trait SeriesArticle { } public function testMarkAllArticlesReadAndUnstarred(): void { - Arsse::$db->articleMark($this->user, ['read'=>true,'starred'=>false]); + Arsse::$db->articleMark($this->user, ['read' => true,'starred' => false]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][8][2] = 1; @@ -726,7 +726,7 @@ trait SeriesArticle { } public function testSetNoteForAllArticles(): void { - Arsse::$db->articleMark($this->user, ['note'=>"New note"]); + Arsse::$db->articleMark($this->user, ['note' => "New note"]); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][8][5] = "New note"; @@ -745,7 +745,7 @@ trait SeriesArticle { } public function testMarkATreeFolder(): void { - Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(7)); + Arsse::$db->articleMark($this->user, ['read' => true], (new Context)->folder(7)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][] = [13,5,1,0,$now,'']; @@ -756,7 +756,7 @@ trait SeriesArticle { } public function testMarkALeafFolder(): void { - Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(8)); + Arsse::$db->articleMark($this->user, ['read' => true], (new Context)->folder(8)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][] = [13,5,1,0,$now,'']; @@ -766,11 +766,11 @@ trait SeriesArticle { public function testMarkAMissingFolder(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); - Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(42)); + Arsse::$db->articleMark($this->user, ['read' => true], (new Context)->folder(42)); } public function testMarkASubscription(): void { - Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->subscription(13)); + Arsse::$db->articleMark($this->user, ['read' => true], (new Context)->subscription(13)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][] = [13,5,1,0,$now,'']; @@ -780,11 +780,11 @@ trait SeriesArticle { public function testMarkAMissingSubscription(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); - Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(2112)); + Arsse::$db->articleMark($this->user, ['read' => true], (new Context)->folder(2112)); } public function testMarkAnArticle(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->article(20)); + Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->article(20)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][9][3] = 1; @@ -793,7 +793,7 @@ trait SeriesArticle { } public function testMarkMultipleArticles(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->articles([2,4,7,20])); + 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); $state['arsse_marks']['rows'][9][3] = 1; @@ -803,7 +803,7 @@ trait SeriesArticle { } public function testMarkMultipleArticlessUnreadAndStarred(): void { - Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles([2,4,7,20])); + 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); $state['arsse_marks']['rows'][9][2] = 0; @@ -816,16 +816,16 @@ trait SeriesArticle { } public function testMarkTooManyMultipleArticles(): void { - $this->assertSame(7, Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles(range(1, Database::LIMIT_SET_SIZE * 3)))); + $this->assertSame(7, Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true], (new Context)->articles(range(1, Database::LIMIT_SET_SIZE * 3)))); } public function testMarkAMissingArticle(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->article(1)); + Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->article(1)); } public function testMarkAnEdition(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(1001)); + Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->edition(1001)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][9][3] = 1; @@ -834,7 +834,7 @@ trait SeriesArticle { } public function testMarkMultipleEditions(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->editions([2,4,7,20])); + 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); $state['arsse_marks']['rows'][9][3] = 1; @@ -844,13 +844,13 @@ trait SeriesArticle { } public function testMarkMultipleMissingEditions(): void { - $this->assertSame(0, Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->editions([500,501]))); + $this->assertSame(0, Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->editions([500,501]))); $state = $this->primeExpectations($this->data, $this->checkTables); $this->compareExpectations(static::$drv, $state); } public function testMarkMultipleEditionsUnread(): void { - Arsse::$db->articleMark($this->user, ['read'=>false], (new Context)->editions([2,4,7,1001])); + 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); $state['arsse_marks']['rows'][9][2] = 0; @@ -861,7 +861,7 @@ trait SeriesArticle { } public function testMarkMultipleEditionsUnreadWithStale(): void { - Arsse::$db->articleMark($this->user, ['read'=>false], (new Context)->editions([2,4,7,20])); + 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); $state['arsse_marks']['rows'][11][2] = 0; @@ -870,7 +870,7 @@ trait SeriesArticle { } public function testMarkMultipleEditionsUnreadAndStarredWithStale(): void { - Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions([2,4,7,20])); + 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); $state['arsse_marks']['rows'][9][3] = 1; @@ -882,17 +882,17 @@ trait SeriesArticle { } public function testMarkTooManyMultipleEditions(): void { - $this->assertSame(7, Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions(range(1, 51)))); + $this->assertSame(7, Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true], (new Context)->editions(range(1, 51)))); } public function testMarkAStaleEditionUnread(): void { - Arsse::$db->articleMark($this->user, ['read'=>false], (new Context)->edition(20)); // no changes occur + Arsse::$db->articleMark($this->user, ['read' => false], (new Context)->edition(20)); // no changes occur $state = $this->primeExpectations($this->data, $this->checkTables); $this->compareExpectations(static::$drv, $state); } public function testMarkAStaleEditionStarred(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(20)); + Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->edition(20)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][9][3] = 1; @@ -901,7 +901,7 @@ trait SeriesArticle { } public function testMarkAStaleEditionUnreadAndStarred(): void { - Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->edition(20)); // only starred is changed + 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); $state['arsse_marks']['rows'][9][3] = 1; @@ -910,18 +910,18 @@ trait SeriesArticle { } public function testMarkAStaleEditionUnreadAndUnstarred(): void { - Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>false], (new Context)->edition(20)); // no changes occur + 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(static::$drv, $state); } public function testMarkAMissingEdition(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(2)); + Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->edition(2)); } public function testMarkByOldestEdition(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->oldestEdition(19)); + Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->oldestEdition(19)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][8][3] = 1; @@ -932,7 +932,7 @@ trait SeriesArticle { } public function testMarkByLatestEdition(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->latestEdition(20)); + Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->latestEdition(20)); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][8][3] = 1; @@ -945,7 +945,7 @@ trait SeriesArticle { } public function testMarkByLastMarked(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->markedSince('2017-01-01T00:00:00Z')); + Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->markedSince('2017-01-01T00:00:00Z')); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][8][3] = 1; @@ -956,7 +956,7 @@ trait SeriesArticle { } public function testMarkByNotLastMarked(): void { - Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->notMarkedSince('2000-01-01T00:00:00Z')); + Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->notMarkedSince('2000-01-01T00:00:00Z')); $now = Date::transform(time(), "sql"); $state = $this->primeExpectations($this->data, $this->checkTables); $state['arsse_marks']['rows'][] = [13,5,0,1,$now,'']; @@ -967,7 +967,7 @@ trait SeriesArticle { public function testMarkArticlesWithoutAuthority(): void { \Phake::when(Arsse::$user)->authorize->thenReturn(false); $this->assertException("notAuthorized", "User", "ExceptionAuthz"); - Arsse::$db->articleMark($this->user, ['read'=>false]); + Arsse::$db->articleMark($this->user, ['read' => false]); } public function testCountArticles(): void { diff --git a/tests/cases/Database/SeriesCleanup.php b/tests/cases/Database/SeriesCleanup.php index 3a33f65..4746ed8 100644 --- a/tests/cases/Database/SeriesCleanup.php +++ b/tests/cases/Database/SeriesCleanup.php @@ -16,7 +16,7 @@ trait SeriesCleanup { 'userSessionLifetime' => "PT24H", ]); // set up the test data - $nowish = gmdate("Y-m-d H:i:s", strtotime("now - 1 minute")); + $nowish = gmdate("Y-m-d H:i:s", strtotime("now - 1 minute")); $yesterday = gmdate("Y-m-d H:i:s", strtotime("now - 1 day")); $daybefore = gmdate("Y-m-d H:i:s", strtotime("now - 2 days")); $daysago = gmdate("Y-m-d H:i:s", strtotime("now - 7 days")); @@ -53,7 +53,7 @@ trait SeriesCleanup { 'columns' => [ 'id' => "str", 'class' => "str", - 'user' => "str", + 'user' => "str", 'expires' => "datetime", ], 'rows' => [ @@ -76,7 +76,7 @@ trait SeriesCleanup { [2,"http://example.com/2","",$yesterday,0], [3,"http://example.com/3","",null,0], [4,"http://example.com/4","",$nowish,0], - ] + ], ], 'arsse_subscriptions' => [ 'columns' => [ @@ -89,7 +89,7 @@ trait SeriesCleanup { [1,'jane.doe@example.com',1], // other subscriptions exist for article cleanup tests [2,'john.doe@example.com',1], - ] + ], ], 'arsse_articles' => [ 'columns' => [ @@ -110,7 +110,7 @@ trait SeriesCleanup { [7,1,"","","",$weeksago], // meets the unread threshold without marks, thus is deleted [8,1,"","","",$weeksago], // meets the unread threshold even with marks, thus is deleted [9,1,"","","",$weeksago], // meets the read threshold, thus is deleted - ] + ], ], 'arsse_editions' => [ 'columns' => [ @@ -124,7 +124,7 @@ trait SeriesCleanup { [4,4], [201,1], [102,2], - ] + ], ], 'arsse_marks' => [ 'columns' => [ @@ -142,7 +142,7 @@ trait SeriesCleanup { [8,1,1,0,$weeksago], [9,1,1,0,$daysago], [9,2,1,0,$daysago], - ] + ], ], ]; } @@ -155,7 +155,7 @@ trait SeriesCleanup { Arsse::$db->feedCleanup(); $now = gmdate("Y-m-d H:i:s"); $state = $this->primeExpectations($this->data, [ - 'arsse_feeds' => ["id","orphaned"] + 'arsse_feeds' => ["id","orphaned"], ]); $state['arsse_feeds']['rows'][0][1] = null; unset($state['arsse_feeds']['rows'][1]); @@ -170,7 +170,7 @@ trait SeriesCleanup { Arsse::$db->feedCleanup(); $now = gmdate("Y-m-d H:i:s"); $state = $this->primeExpectations($this->data, [ - 'arsse_feeds' => ["id","orphaned"] + 'arsse_feeds' => ["id","orphaned"], ]); $state['arsse_feeds']['rows'][0][1] = null; $state['arsse_feeds']['rows'][2][1] = $now; @@ -180,7 +180,7 @@ trait SeriesCleanup { public function testCleanUpOldArticlesWithStandardRetention(): void { Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ - 'arsse_articles' => ["id"] + 'arsse_articles' => ["id"], ]); foreach ([7,8,9] as $id) { unset($state['arsse_articles']['rows'][$id - 1]); @@ -194,7 +194,7 @@ trait SeriesCleanup { ]); Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ - 'arsse_articles' => ["id"] + 'arsse_articles' => ["id"], ]); foreach ([7,8] as $id) { unset($state['arsse_articles']['rows'][$id - 1]); @@ -208,7 +208,7 @@ trait SeriesCleanup { ]); Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ - 'arsse_articles' => ["id"] + 'arsse_articles' => ["id"], ]); foreach ([9] as $id) { unset($state['arsse_articles']['rows'][$id - 1]); @@ -218,12 +218,12 @@ trait SeriesCleanup { public function testCleanUpOldArticlesWithUnlimitedRetention(): void { Arsse::$conf->import([ - 'purgeArticlesRead' => null, + 'purgeArticlesRead' => null, 'purgeArticlesUnread' => null, ]); Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ - 'arsse_articles' => ["id"] + 'arsse_articles' => ["id"], ]); $this->compareExpectations(static::$drv, $state); } @@ -231,7 +231,7 @@ trait SeriesCleanup { public function testCleanUpExpiredSessions(): void { Arsse::$db->sessionCleanup(); $state = $this->primeExpectations($this->data, [ - 'arsse_sessions' => ["id"] + 'arsse_sessions' => ["id"], ]); foreach ([3,4,5] as $id) { unset($state['arsse_sessions']['rows'][$id - 1]); @@ -242,7 +242,7 @@ trait SeriesCleanup { public function testCleanUpExpiredTokens(): void { Arsse::$db->tokenCleanup(); $state = $this->primeExpectations($this->data, [ - 'arsse_tokens' => ["id", "class"] + 'arsse_tokens' => ["id", "class"], ]); foreach ([2] as $id) { unset($state['arsse_tokens']['rows'][$id - 1]); diff --git a/tests/cases/Database/SeriesFeed.php b/tests/cases/Database/SeriesFeed.php index ee19bb1..d4a7521 100644 --- a/tests/cases/Database/SeriesFeed.php +++ b/tests/cases/Database/SeriesFeed.php @@ -11,7 +11,7 @@ use JKingWeb\Arsse\Arsse; trait SeriesFeed { protected function setUpSeriesFeed(): void { // set up the test data - $past = gmdate("Y-m-d H:i:s", strtotime("now - 1 minute")); + $past = gmdate("Y-m-d H:i:s", strtotime("now - 1 minute")); $future = gmdate("Y-m-d H:i:s", strtotime("now + 1 minute")); $now = gmdate("Y-m-d H:i:s", strtotime("now")); $this->data = [ @@ -42,7 +42,7 @@ trait SeriesFeed { [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], - ] + ], ], 'arsse_subscriptions' => [ 'columns' => [ @@ -57,7 +57,7 @@ trait SeriesFeed { [4,'john.doe@example.com',4], [5,'john.doe@example.com',5], [6,'jane.doe@example.com',1], - ] + ], ], 'arsse_articles' => [ 'columns' => [ @@ -82,8 +82,8 @@ trait SeriesFeed { [4,1,'http://example.com/4','Article title 4','','2000-01-04 00:00:00','2000-01-04 00:00:00','

Article content 4

','804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8','f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3','ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9',$past], [5,1,'http://example.com/5','Article title 5','','2000-01-05 00:00:00','2000-01-05 00:00:00','

Article content 5

','db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41','d40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022','834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900','43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba',$past], [6,2,'http://example.com/1','Article title 1','','2000-01-01 00:00:00','2000-01-01 00:00:00','

Article content 1

','e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda','f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6','fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4','18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207',$past], - [7,5,'' ,'' ,'','2000-01-01 00:00:00','2000-01-01 00:00:00','' ,'205e986f4f8b3acfa281227beadb14f5e8c32c8dae4737f888c94c0df49c56f8','' ,'' ,'' ,$past], - ] + [7,5,'', '', '','2000-01-01 00:00:00','2000-01-01 00:00:00','', '205e986f4f8b3acfa281227beadb14f5e8c32c8dae4737f888c94c0df49c56f8','', '', '', $past], + ], ], 'arsse_editions' => [ 'columns' => [ @@ -97,7 +97,7 @@ trait SeriesFeed { [3,3,$past], [4,4,$past], [5,5,$past], - ] + ], ], 'arsse_marks' => [ 'columns' => [ @@ -118,7 +118,7 @@ trait SeriesFeed { [1,1,1,0,$past], [3,1,1,0,$past], [4,1,0,1,$past], - ] + ], ], 'arsse_enclosures' => [ 'columns' => [ @@ -128,16 +128,16 @@ trait SeriesFeed { ], 'rows' => [ [7,'http://example.com/png','image/png'], - ] + ], ], 'arsse_categories' => [ 'columns' => [ - 'article' => "int", + 'article' => "int", 'name' => "str", ], 'rows' => [ - [7,'Syrinx'] - ] + [7,'Syrinx'], + ], ], ]; $this->matches = [ @@ -191,7 +191,7 @@ trait SeriesFeed { ]); $state['arsse_articles']['rows'][2] = [3,1,'http://example.com/3','Article title 3 (updated)','','2000-01-03 00:00:00','2000-01-03 00:00:00','

Article content 3

','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','6cc99be662ef3486fef35a890123f18d74c29a32d714802d743c5b4ef713315a','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','d5faccc13bf8267850a1e8e61f95950a0f34167df2c8c58011c0aaa6367026ac',$now]; $state['arsse_articles']['rows'][3] = [4,1,'http://example.com/4','Article title 4','','2000-01-04 00:00:00','2000-01-04 00:00:01','

Article content 4

','804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8','f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3','ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9',$now]; - $state['arsse_articles']['rows'][] = [8,1,'http://example.com/6','Article title 6','','2000-01-06 00:00:00','2000-01-06 00:00:00','

Article content 6

','b3461ab8e8759eeb1d65a818c65051ec00c1dfbbb32a3c8f6999434e3e3b76ab','91d051a8e6749d014506848acd45e959af50bf876427c4f0e3a1ec0f04777b51','211d78b1a040d40d17e747a363cc283f58767b2e502630d8de9b8f1d5e941d18','5ed68ccb64243b8c1931241d2c9276274c3b1d87f223634aa7a1ab0141292ca7',$now]; + $state['arsse_articles']['rows'][] = [8,1,'http://example.com/6','Article title 6','','2000-01-06 00:00:00','2000-01-06 00:00:00','

Article content 6

','b3461ab8e8759eeb1d65a818c65051ec00c1dfbbb32a3c8f6999434e3e3b76ab','91d051a8e6749d014506848acd45e959af50bf876427c4f0e3a1ec0f04777b51','211d78b1a040d40d17e747a363cc283f58767b2e502630d8de9b8f1d5e941d18','5ed68ccb64243b8c1931241d2c9276274c3b1d87f223634aa7a1ab0141292ca7',$now]; $state['arsse_editions']['rows'] = array_merge($state['arsse_editions']['rows'], [ [6,8,$now], [7,3,$now], diff --git a/tests/cases/Database/SeriesFolder.php b/tests/cases/Database/SeriesFolder.php index bc1ae3a..6d69f64 100644 --- a/tests/cases/Database/SeriesFolder.php +++ b/tests/cases/Database/SeriesFolder.php @@ -45,7 +45,7 @@ trait SeriesFolder { [4, "jane.doe@example.com", null, "Politics"], [5, "john.doe@example.com", null, "Politics"], [6, "john.doe@example.com", 2, "Politics"], - ] + ], ], 'arsse_feeds' => [ 'columns' => [ @@ -67,7 +67,7 @@ trait SeriesFolder { [11,"http://example.com/11", "Feed 11"], [12,"http://example.com/12", "Feed 12"], [13,"http://example.com/13", "Feed 13"], - ] + ], ], 'arsse_subscriptions' => [ 'columns' => [ @@ -88,7 +88,7 @@ trait SeriesFolder { [9, "jane.doe@example.com",2, 4], [10,"jane.doe@example.com",3, 4], [11,"jane.doe@example.com",4, 4], - ] + ], ], ]; } diff --git a/tests/cases/Database/SeriesLabel.php b/tests/cases/Database/SeriesLabel.php index 74fdee4..db9c498 100644 --- a/tests/cases/Database/SeriesLabel.php +++ b/tests/cases/Database/SeriesLabel.php @@ -42,7 +42,7 @@ trait SeriesLabel { [7, "john.doe@example.net", null, "Technology"], [8, "john.doe@example.net", 7, "Software"], [9, "john.doe@example.net", null, "Politics"], - ] + ], ], 'arsse_feeds' => [ 'columns' => [ @@ -63,7 +63,7 @@ trait SeriesLabel { [11,"http://example.com/11"], [12,"http://example.com/12"], [13,"http://example.com/13"], - ] + ], ], 'arsse_subscriptions' => [ 'columns' => [ @@ -87,7 +87,7 @@ trait SeriesLabel { [12,"john.doe@example.net",2,9], [13,"john.doe@example.net",3,8], [14,"john.doe@example.net",4,7], - ] + ], ], 'arsse_articles' => [ 'columns' => [ @@ -131,7 +131,7 @@ trait SeriesLabel { [103,12,'http://example.com/3','Article title 3','','2000-01-03 00:00:00','2000-01-03 00:00:03','

Article content 3

','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b','2000-01-03 03:00:00'], [104,12,'http://example.com/4','Article title 4','','2000-01-04 00:00:00','2000-01-04 00:00:04','

Article content 4

','804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8','f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3','ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9','2000-01-04 04:00:00'], [105,13,'http://example.com/5','Article title 5','','2000-01-05 00:00:00','2000-01-05 00:00:05','

Article content 5

','db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41','d40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022','834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900','43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba','2000-01-05 05:00:00'], - ] + ], ], 'arsse_enclosures' => [ 'columns' => [ @@ -145,7 +145,7 @@ trait SeriesLabel { [104,"http://example.com/image","image/svg+xml"], [105,"http://example.com/audio","audio/ogg"], - ] + ], ], 'arsse_editions' => [ 'columns' => [ @@ -184,7 +184,7 @@ trait SeriesLabel { [205,105], [305,105], [1001,20], - ] + ], ], 'arsse_marks' => [ 'columns' => [ @@ -192,7 +192,7 @@ trait SeriesLabel { 'article' => "int", 'read' => "bool", 'starred' => "bool", - 'modified' => "datetime" + 'modified' => "datetime", ], 'rows' => [ [1, 1,1,1,'2000-01-01 00:00:00'], @@ -207,7 +207,7 @@ trait SeriesLabel { [11, 20,1,0,'2017-01-01 00:00:00'], [12, 3,0,1,'2017-01-01 00:00:00'], [12, 4,1,1,'2017-01-01 00:00:00'], - ] + ], ], 'arsse_labels' => [ 'columns' => [ @@ -224,10 +224,10 @@ trait SeriesLabel { ], 'arsse_label_members' => [ 'columns' => [ - 'label' => "int", - 'article' => "int", + 'label' => "int", + 'article' => "int", 'subscription' => "int", - 'assigned' => "bool", + 'assigned' => "bool", ], 'rows' => [ [1, 1,1,1], diff --git a/tests/cases/Database/SeriesSession.php b/tests/cases/Database/SeriesSession.php index f3a84b6..9a354f6 100644 --- a/tests/cases/Database/SeriesSession.php +++ b/tests/cases/Database/SeriesSession.php @@ -17,7 +17,7 @@ trait SeriesSession { 'userSessionLifetime' => "PT24H", ]); // set up the test data - $past = gmdate("Y-m-d H:i:s", strtotime("now - 1 minute")); + $past = gmdate("Y-m-d H:i:s", strtotime("now - 1 minute")); $future = gmdate("Y-m-d H:i:s", strtotime("now + 1 minute")); $faroff = gmdate("Y-m-d H:i:s", strtotime("now + 1 hour")); $old = gmdate("Y-m-d H:i:s", strtotime("now - 2 days")); @@ -55,12 +55,12 @@ trait SeriesSession { public function testResumeAValidSession(): void { $exp1 = [ - 'id' => "80fa94c1a11f11e78667001e673b2560", - 'user' => "jane.doe@example.com" + 'id' => "80fa94c1a11f11e78667001e673b2560", + 'user' => "jane.doe@example.com", ]; $exp2 = [ - 'id' => "da772f8fa13c11e78667001e673b2560", - 'user' => "john.doe@example.com" + 'id' => "da772f8fa13c11e78667001e673b2560", + 'user' => "john.doe@example.com", ]; $this->assertArraySubset($exp1, Arsse::$db->sessionResume("80fa94c1a11f11e78667001e673b2560")); $this->assertArraySubset($exp2, Arsse::$db->sessionResume("da772f8fa13c11e78667001e673b2560")); diff --git a/tests/cases/Database/SeriesSubscription.php b/tests/cases/Database/SeriesSubscription.php index a89319e..d8614e2 100644 --- a/tests/cases/Database/SeriesSubscription.php +++ b/tests/cases/Database/SeriesSubscription.php @@ -38,7 +38,7 @@ trait SeriesSubscription { [4, "jane.doe@example.com", null, "Politics"], [5, "john.doe@example.com", null, "Politics"], [6, "john.doe@example.com", 2, "Politics"], - ] + ], ], 'arsse_feeds' => [ 'columns' => [ @@ -51,7 +51,7 @@ trait SeriesSubscription { 'next_fetch' => "datetime", 'favicon' => "str", ], - 'rows' => [] // filled in the series setup + 'rows' => [], // filled in the series setup ], 'arsse_subscriptions' => [ 'columns' => [ @@ -67,7 +67,7 @@ trait SeriesSubscription { [1,"john.doe@example.com",2,null,null,1,2], [2,"jane.doe@example.com",2,null,null,0,0], [3,"john.doe@example.com",3,"Ook",2,0,1], - ] + ], ], 'arsse_tags' => [ 'columns' => [ @@ -84,9 +84,9 @@ trait SeriesSubscription { ], 'arsse_tag_members' => [ 'columns' => [ - 'tag' => "int", + 'tag' => "int", 'subscription' => "int", - 'assigned' => "bool", + 'assigned' => "bool", ], 'rows' => [ [1,1,1], @@ -113,7 +113,7 @@ trait SeriesSubscription { [6,3,"","",""], [7,3,"","",""], [8,3,"","",""], - ] + ], ], 'arsse_marks' => [ 'columns' => [ @@ -131,7 +131,7 @@ trait SeriesSubscription { [1,1,1,0], [7,3,1,0], [8,3,0,0], - ] + ], ], ]; $this->data['arsse_feeds']['rows'] = [ @@ -379,9 +379,9 @@ trait SeriesSubscription { public function testSetThePropertiesOfASubscription(): void { Arsse::$db->subscriptionPropertiesSet($this->user, 1, [ - 'title' => "Ook Ook", - 'folder' => 3, - 'pinned' => false, + 'title' => "Ook Ook", + 'folder' => 3, + 'pinned' => false, 'order_type' => 0, ]); \Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionPropertiesSet"); diff --git a/tests/cases/Database/SeriesTag.php b/tests/cases/Database/SeriesTag.php index 07b99fd..f6a3f4e 100644 --- a/tests/cases/Database/SeriesTag.php +++ b/tests/cases/Database/SeriesTag.php @@ -44,7 +44,7 @@ trait SeriesTag { [11,"http://example.com/11",""], [12,"http://example.com/12",""], [13,"http://example.com/13",""], - ] + ], ], 'arsse_subscriptions' => [ 'columns' => [ @@ -68,7 +68,7 @@ trait SeriesTag { [12,"john.doe@example.net", 2,null], [13,"john.doe@example.net", 3,null], [14,"john.doe@example.net", 4,null], - ] + ], ], 'arsse_tags' => [ 'columns' => [ @@ -85,9 +85,9 @@ trait SeriesTag { ], 'arsse_tag_members' => [ 'columns' => [ - 'tag' => "int", + 'tag' => "int", 'subscription' => "int", - 'assigned' => "bool", + 'assigned' => "bool", ], 'rows' => [ [1,1,1], diff --git a/tests/cases/Database/SeriesToken.php b/tests/cases/Database/SeriesToken.php index 8ed84e2..aad4a87 100644 --- a/tests/cases/Database/SeriesToken.php +++ b/tests/cases/Database/SeriesToken.php @@ -11,7 +11,7 @@ use JKingWeb\Arsse\Arsse; trait SeriesToken { protected function setUpSeriesToken(): void { // set up the test data - $past = gmdate("Y-m-d H:i:s", strtotime("now - 1 minute")); + $past = gmdate("Y-m-d H:i:s", strtotime("now - 1 minute")); $future = gmdate("Y-m-d H:i:s", strtotime("now + 1 minute")); $faroff = gmdate("Y-m-d H:i:s", strtotime("now + 1 hour")); $old = gmdate("Y-m-d H:i:s", strtotime("now - 2 days")); @@ -30,7 +30,7 @@ trait SeriesToken { 'columns' => [ 'id' => "str", 'class' => "str", - 'user' => "str", + 'user' => "str", 'expires' => "datetime", ], 'rows' => [ @@ -49,19 +49,19 @@ trait SeriesToken { public function testLookUpAValidToken(): void { $exp1 = [ - 'id' => "80fa94c1a11f11e78667001e673b2560", + 'id' => "80fa94c1a11f11e78667001e673b2560", 'class' => "fever.login", - 'user' => "jane.doe@example.com" + 'user' => "jane.doe@example.com", ]; $exp2 = [ - 'id' => "da772f8fa13c11e78667001e673b2560", + 'id' => "da772f8fa13c11e78667001e673b2560", 'class' => "class.class", - 'user' => "john.doe@example.com" + 'user' => "john.doe@example.com", ]; $exp3 = [ - 'id' => "ab3b3eb8a13311e78667001e673b2560", + 'id' => "ab3b3eb8a13311e78667001e673b2560", 'class' => "class.class", - 'user' => "jane.doe@example.com" + 'user' => "jane.doe@example.com", ]; $this->assertArraySubset($exp1, Arsse::$db->tokenLookup("fever.login", "80fa94c1a11f11e78667001e673b2560")); $this->assertArraySubset($exp2, Arsse::$db->tokenLookup("class.class", "da772f8fa13c11e78667001e673b2560")); diff --git a/tests/cases/Database/TestDatabase.php b/tests/cases/Database/TestDatabase.php index 0bce916..581bc23 100644 --- a/tests/cases/Database/TestDatabase.php +++ b/tests/cases/Database/TestDatabase.php @@ -11,7 +11,7 @@ use JKingWeb\Arsse\Database; /** @covers \JKingWeb\Arsse\Database */ class TestDatabase extends \JKingWeb\Arsse\Test\AbstractTest { protected $db = null; - + public function setUp(): void { self::clearData(); self::setConf(); @@ -49,7 +49,7 @@ class TestDatabase extends \JKingWeb\Arsse\Test\AbstractTest { ["?,?", [null, null], [null, null], "str"], ["null", [], array_fill(0, $l, null), "str"], ["$intList", [], $ints, "int"], - ["$intList,".($l+1), [], array_merge($ints, [$l+1]), "int"], + ["$intList,".($l + 1), [], array_merge($ints, [$l + 1]), "int"], ["$intList,0", [], array_merge($ints, ["OOK"]), "int"], ["$intList", [], array_merge($ints, [null]), "int"], ["$stringList,''", [], array_merge($strings, [""]), "str"], diff --git a/tests/cases/Db/BaseDriver.php b/tests/cases/Db/BaseDriver.php index 017deaa..94091ac 100644 --- a/tests/cases/Db/BaseDriver.php +++ b/tests/cases/Db/BaseDriver.php @@ -17,8 +17,8 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { protected $lock; protected $setVersion; protected static $conf = [ - 'dbTimeoutExec' => 0.5, - 'dbTimeoutLock' => 0.001, + 'dbTimeoutExec' => 0.5, + 'dbTimeoutLock' => 0.001, 'dbSQLite3Timeout' => 0, //'dbSQLite3File' => "(temporary file)", ]; @@ -29,7 +29,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { static::setConf(static::$conf); static::$interface = static::dbInterface(); } - + public function setUp(): void { self::clearData(); self::setConf(static::$conf); @@ -75,12 +75,12 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { } # TESTS - + public function testFetchDriverName(): void { $class = get_class($this->drv); $this->assertTrue(strlen($class::driverName()) > 0); } - + public function testFetchSchemaId(): void { $class = get_class($this->drv); $this->assertTrue(strlen($class::schemaID()) > 0); diff --git a/tests/cases/Db/BaseResult.php b/tests/cases/Db/BaseResult.php index 3391cf0..4d3d2c4 100644 --- a/tests/cases/Db/BaseResult.php +++ b/tests/cases/Db/BaseResult.php @@ -21,7 +21,7 @@ abstract class BaseResult extends \JKingWeb\Arsse\Test\AbstractTest { static::setConf(); static::$interface = static::dbInterface(); } - + public function setUp(): void { self::clearData(); self::setConf(); diff --git a/tests/cases/Db/BaseStatement.php b/tests/cases/Db/BaseStatement.php index f2f166f..206aed7 100644 --- a/tests/cases/Db/BaseStatement.php +++ b/tests/cases/Db/BaseStatement.php @@ -21,7 +21,7 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest { static::setConf(); static::$interface = static::dbInterface(); } - + public function setUp(): void { self::clearData(); self::setConf(); @@ -134,138 +134,138 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest { $dateImmutable = new \DateTimeImmutable("Noon Today", new \DateTimezone("America/Toronto")); $dateUTC = new \DateTime("@".$dateMutable->getTimestamp(), new \DateTimezone("UTC")); $tests = [ - 'Null as integer' => [null, "integer", "null"], - 'Null as float' => [null, "float", "null"], - 'Null as string' => [null, "string", "null"], - 'Null as datetime' => [null, "datetime", "null"], - 'Null as boolean' => [null, "boolean", "null"], - 'Null as strict integer' => [null, "strict integer", "0"], - 'Null as strict float' => [null, "strict float", "0.0"], - 'Null as strict string' => [null, "strict string", "''"], - 'Null as strict datetime' => [null, "strict datetime", "'0001-01-01 00:00:00'"], - 'Null as strict boolean' => [null, "strict boolean", "0"], - 'True as integer' => [true, "integer", "1"], - 'True as float' => [true, "float", "1.0"], - 'True as string' => [true, "string", "'1'"], - 'True as datetime' => [true, "datetime", "null"], - 'True as boolean' => [true, "boolean", "1"], - 'True as strict integer' => [true, "strict integer", "1"], - 'True as strict float' => [true, "strict float", "1.0"], - 'True as strict string' => [true, "strict string", "'1'"], - 'True as strict datetime' => [true, "strict datetime", "'0001-01-01 00:00:00'"], - 'True as strict boolean' => [true, "strict boolean", "1"], - 'False as integer' => [false, "integer", "0"], - 'False as float' => [false, "float", "0.0"], - 'False as string' => [false, "string", "''"], - 'False as datetime' => [false, "datetime", "null"], - 'False as boolean' => [false, "boolean", "0"], - 'False as strict integer' => [false, "strict integer", "0"], - 'False as strict float' => [false, "strict float", "0.0"], - 'False as strict string' => [false, "strict string", "''"], - 'False as strict datetime' => [false, "strict datetime", "'0001-01-01 00:00:00'"], - 'False as strict boolean' => [false, "strict boolean", "0"], - 'Integer as integer' => [2112, "integer", "2112"], - 'Integer as float' => [2112, "float", "2112.0"], - 'Integer as string' => [2112, "string", "'2112'"], - 'Integer as datetime' => [2112, "datetime", "'1970-01-01 00:35:12'"], - 'Integer as boolean' => [2112, "boolean", "1"], - 'Integer as strict integer' => [2112, "strict integer", "2112"], - 'Integer as strict float' => [2112, "strict float", "2112.0"], - 'Integer as strict string' => [2112, "strict string", "'2112'"], - 'Integer as strict datetime' => [2112, "strict datetime", "'1970-01-01 00:35:12'"], - 'Integer as strict boolean' => [2112, "strict boolean", "1"], - 'Integer zero as integer' => [0, "integer", "0"], - 'Integer zero as float' => [0, "float", "0.0"], - 'Integer zero as string' => [0, "string", "'0'"], - 'Integer zero as datetime' => [0, "datetime", "'1970-01-01 00:00:00'"], - 'Integer zero as boolean' => [0, "boolean", "0"], - 'Integer zero as strict integer' => [0, "strict integer", "0"], - 'Integer zero as strict float' => [0, "strict float", "0.0"], - 'Integer zero as strict string' => [0, "strict string", "'0'"], - 'Integer zero as strict datetime' => [0, "strict datetime", "'1970-01-01 00:00:00'"], - 'Integer zero as strict boolean' => [0, "strict boolean", "0"], - 'Float as integer' => [2112.5, "integer", "2112"], - 'Float as float' => [2112.5, "float", "2112.5"], - 'Float as string' => [2112.5, "string", "'2112.5'"], - 'Float as datetime' => [2112.5, "datetime", "'1970-01-01 00:35:12'"], - 'Float as boolean' => [2112.5, "boolean", "1"], - 'Float as strict integer' => [2112.5, "strict integer", "2112"], - 'Float as strict float' => [2112.5, "strict float", "2112.5"], - 'Float as strict string' => [2112.5, "strict string", "'2112.5'"], - 'Float as strict datetime' => [2112.5, "strict datetime", "'1970-01-01 00:35:12'"], - 'Float as strict boolean' => [2112.5, "strict boolean", "1"], - 'Float zero as integer' => [0.0, "integer", "0"], - 'Float zero as float' => [0.0, "float", "0.0"], - 'Float zero as string' => [0.0, "string", "'0'"], - 'Float zero as datetime' => [0.0, "datetime", "'1970-01-01 00:00:00'"], - 'Float zero as boolean' => [0.0, "boolean", "0"], - 'Float zero as strict integer' => [0.0, "strict integer", "0"], - 'Float zero as strict float' => [0.0, "strict float", "0.0"], - 'Float zero as strict string' => [0.0, "strict string", "'0'"], - 'Float zero as strict datetime' => [0.0, "strict datetime", "'1970-01-01 00:00:00'"], - 'Float zero as strict boolean' => [0.0, "strict boolean", "0"], - 'ASCII string as integer' => ["Random string", "integer", "0"], - 'ASCII string as float' => ["Random string", "float", "0.0"], - 'ASCII string as string' => ["Random string", "string", "'Random string'"], - 'ASCII string as datetime' => ["Random string", "datetime", "null"], - 'ASCII string as boolean' => ["Random string", "boolean", "1"], - 'ASCII string as strict integer' => ["Random string", "strict integer", "0"], - 'ASCII string as strict float' => ["Random string", "strict float", "0.0"], - 'ASCII string as strict string' => ["Random string", "strict string", "'Random string'"], - 'ASCII string as strict datetime' => ["Random string", "strict datetime", "'0001-01-01 00:00:00'"], - 'ASCII string as strict boolean' => ["Random string", "strict boolean", "1"], - 'UTF-8 string as integer' => ["\u{e9}", "integer", "0"], - 'UTF-8 string as float' => ["\u{e9}", "float", "0.0"], - 'UTF-8 string as string' => ["\u{e9}", "string", "char(233)"], - 'UTF-8 string as datetime' => ["\u{e9}", "datetime", "null"], - 'UTF-8 string as boolean' => ["\u{e9}", "boolean", "1"], - 'UTF-8 string as strict integer' => ["\u{e9}", "strict integer", "0"], - 'UTF-8 string as strict float' => ["\u{e9}", "strict float", "0.0"], - 'UTF-8 string as strict string' => ["\u{e9}", "strict string", "char(233)"], - 'UTF-8 string as strict datetime' => ["\u{e9}", "strict datetime", "'0001-01-01 00:00:00'"], - 'UTF-8 string as strict boolean' => ["\u{e9}", "strict boolean", "1"], - 'ISO 8601 string as integer' => ["2017-01-09T13:11:17", "integer", "0"], - 'ISO 8601 string as float' => ["2017-01-09T13:11:17", "float", "0.0"], - 'ISO 8601 string as string' => ["2017-01-09T13:11:17", "string", "'2017-01-09T13:11:17'"], - 'ISO 8601 string as datetime' => ["2017-01-09T13:11:17", "datetime", "'2017-01-09 13:11:17'"], - 'ISO 8601 string as boolean' => ["2017-01-09T13:11:17", "boolean", "1"], - 'ISO 8601 string as strict integer' => ["2017-01-09T13:11:17", "strict integer", "0"], - 'ISO 8601 string as strict float' => ["2017-01-09T13:11:17", "strict float", "0.0"], - 'ISO 8601 string as strict string' => ["2017-01-09T13:11:17", "strict string", "'2017-01-09T13:11:17'"], - 'ISO 8601 string as strict datetime' => ["2017-01-09T13:11:17", "strict datetime", "'2017-01-09 13:11:17'"], - 'ISO 8601 string as strict boolean' => ["2017-01-09T13:11:17", "strict boolean", "1"], - 'Arbitrary date string as integer' => ["Today", "integer", "0"], - 'Arbitrary date string as float' => ["Today", "float", "0.0"], - 'Arbitrary date string as string' => ["Today", "string", "'Today'"], - 'Arbitrary date string as datetime' => ["Today", "datetime", "'".date_create("Today", new \DateTimezone("UTC"))->format("Y-m-d H:i:s")."'"], - 'Arbitrary date string as boolean' => ["Today", "boolean", "1"], - 'Arbitrary date string as strict integer' => ["Today", "strict integer", "0"], - 'Arbitrary date string as strict float' => ["Today", "strict float", "0.0"], - 'Arbitrary date string as strict string' => ["Today", "strict string", "'Today'"], + 'Null as integer' => [null, "integer", "null"], + 'Null as float' => [null, "float", "null"], + 'Null as string' => [null, "string", "null"], + 'Null as datetime' => [null, "datetime", "null"], + 'Null as boolean' => [null, "boolean", "null"], + 'Null as strict integer' => [null, "strict integer", "0"], + 'Null as strict float' => [null, "strict float", "0.0"], + 'Null as strict string' => [null, "strict string", "''"], + 'Null as strict datetime' => [null, "strict datetime", "'0001-01-01 00:00:00'"], + 'Null as strict boolean' => [null, "strict boolean", "0"], + 'True as integer' => [true, "integer", "1"], + 'True as float' => [true, "float", "1.0"], + 'True as string' => [true, "string", "'1'"], + 'True as datetime' => [true, "datetime", "null"], + 'True as boolean' => [true, "boolean", "1"], + 'True as strict integer' => [true, "strict integer", "1"], + 'True as strict float' => [true, "strict float", "1.0"], + 'True as strict string' => [true, "strict string", "'1'"], + 'True as strict datetime' => [true, "strict datetime", "'0001-01-01 00:00:00'"], + 'True as strict boolean' => [true, "strict boolean", "1"], + 'False as integer' => [false, "integer", "0"], + 'False as float' => [false, "float", "0.0"], + 'False as string' => [false, "string", "''"], + 'False as datetime' => [false, "datetime", "null"], + 'False as boolean' => [false, "boolean", "0"], + 'False as strict integer' => [false, "strict integer", "0"], + 'False as strict float' => [false, "strict float", "0.0"], + 'False as strict string' => [false, "strict string", "''"], + 'False as strict datetime' => [false, "strict datetime", "'0001-01-01 00:00:00'"], + 'False as strict boolean' => [false, "strict boolean", "0"], + 'Integer as integer' => [2112, "integer", "2112"], + 'Integer as float' => [2112, "float", "2112.0"], + 'Integer as string' => [2112, "string", "'2112'"], + 'Integer as datetime' => [2112, "datetime", "'1970-01-01 00:35:12'"], + 'Integer as boolean' => [2112, "boolean", "1"], + 'Integer as strict integer' => [2112, "strict integer", "2112"], + 'Integer as strict float' => [2112, "strict float", "2112.0"], + 'Integer as strict string' => [2112, "strict string", "'2112'"], + 'Integer as strict datetime' => [2112, "strict datetime", "'1970-01-01 00:35:12'"], + 'Integer as strict boolean' => [2112, "strict boolean", "1"], + 'Integer zero as integer' => [0, "integer", "0"], + 'Integer zero as float' => [0, "float", "0.0"], + 'Integer zero as string' => [0, "string", "'0'"], + 'Integer zero as datetime' => [0, "datetime", "'1970-01-01 00:00:00'"], + 'Integer zero as boolean' => [0, "boolean", "0"], + 'Integer zero as strict integer' => [0, "strict integer", "0"], + 'Integer zero as strict float' => [0, "strict float", "0.0"], + 'Integer zero as strict string' => [0, "strict string", "'0'"], + 'Integer zero as strict datetime' => [0, "strict datetime", "'1970-01-01 00:00:00'"], + 'Integer zero as strict boolean' => [0, "strict boolean", "0"], + 'Float as integer' => [2112.5, "integer", "2112"], + 'Float as float' => [2112.5, "float", "2112.5"], + 'Float as string' => [2112.5, "string", "'2112.5'"], + 'Float as datetime' => [2112.5, "datetime", "'1970-01-01 00:35:12'"], + 'Float as boolean' => [2112.5, "boolean", "1"], + 'Float as strict integer' => [2112.5, "strict integer", "2112"], + 'Float as strict float' => [2112.5, "strict float", "2112.5"], + 'Float as strict string' => [2112.5, "strict string", "'2112.5'"], + 'Float as strict datetime' => [2112.5, "strict datetime", "'1970-01-01 00:35:12'"], + 'Float as strict boolean' => [2112.5, "strict boolean", "1"], + 'Float zero as integer' => [0.0, "integer", "0"], + 'Float zero as float' => [0.0, "float", "0.0"], + 'Float zero as string' => [0.0, "string", "'0'"], + 'Float zero as datetime' => [0.0, "datetime", "'1970-01-01 00:00:00'"], + 'Float zero as boolean' => [0.0, "boolean", "0"], + 'Float zero as strict integer' => [0.0, "strict integer", "0"], + 'Float zero as strict float' => [0.0, "strict float", "0.0"], + 'Float zero as strict string' => [0.0, "strict string", "'0'"], + 'Float zero as strict datetime' => [0.0, "strict datetime", "'1970-01-01 00:00:00'"], + 'Float zero as strict boolean' => [0.0, "strict boolean", "0"], + 'ASCII string as integer' => ["Random string", "integer", "0"], + 'ASCII string as float' => ["Random string", "float", "0.0"], + 'ASCII string as string' => ["Random string", "string", "'Random string'"], + 'ASCII string as datetime' => ["Random string", "datetime", "null"], + 'ASCII string as boolean' => ["Random string", "boolean", "1"], + 'ASCII string as strict integer' => ["Random string", "strict integer", "0"], + 'ASCII string as strict float' => ["Random string", "strict float", "0.0"], + 'ASCII string as strict string' => ["Random string", "strict string", "'Random string'"], + 'ASCII string as strict datetime' => ["Random string", "strict datetime", "'0001-01-01 00:00:00'"], + 'ASCII string as strict boolean' => ["Random string", "strict boolean", "1"], + 'UTF-8 string as integer' => ["\u{e9}", "integer", "0"], + 'UTF-8 string as float' => ["\u{e9}", "float", "0.0"], + 'UTF-8 string as string' => ["\u{e9}", "string", "char(233)"], + 'UTF-8 string as datetime' => ["\u{e9}", "datetime", "null"], + 'UTF-8 string as boolean' => ["\u{e9}", "boolean", "1"], + 'UTF-8 string as strict integer' => ["\u{e9}", "strict integer", "0"], + 'UTF-8 string as strict float' => ["\u{e9}", "strict float", "0.0"], + 'UTF-8 string as strict string' => ["\u{e9}", "strict string", "char(233)"], + 'UTF-8 string as strict datetime' => ["\u{e9}", "strict datetime", "'0001-01-01 00:00:00'"], + 'UTF-8 string as strict boolean' => ["\u{e9}", "strict boolean", "1"], + 'ISO 8601 string as integer' => ["2017-01-09T13:11:17", "integer", "0"], + 'ISO 8601 string as float' => ["2017-01-09T13:11:17", "float", "0.0"], + 'ISO 8601 string as string' => ["2017-01-09T13:11:17", "string", "'2017-01-09T13:11:17'"], + 'ISO 8601 string as datetime' => ["2017-01-09T13:11:17", "datetime", "'2017-01-09 13:11:17'"], + 'ISO 8601 string as boolean' => ["2017-01-09T13:11:17", "boolean", "1"], + 'ISO 8601 string as strict integer' => ["2017-01-09T13:11:17", "strict integer", "0"], + 'ISO 8601 string as strict float' => ["2017-01-09T13:11:17", "strict float", "0.0"], + 'ISO 8601 string as strict string' => ["2017-01-09T13:11:17", "strict string", "'2017-01-09T13:11:17'"], + 'ISO 8601 string as strict datetime' => ["2017-01-09T13:11:17", "strict datetime", "'2017-01-09 13:11:17'"], + 'ISO 8601 string as strict boolean' => ["2017-01-09T13:11:17", "strict boolean", "1"], + 'Arbitrary date string as integer' => ["Today", "integer", "0"], + 'Arbitrary date string as float' => ["Today", "float", "0.0"], + 'Arbitrary date string as string' => ["Today", "string", "'Today'"], + 'Arbitrary date string as datetime' => ["Today", "datetime", "'".date_create("Today", new \DateTimezone("UTC"))->format("Y-m-d H:i:s")."'"], + 'Arbitrary date string as boolean' => ["Today", "boolean", "1"], + 'Arbitrary date string as strict integer' => ["Today", "strict integer", "0"], + 'Arbitrary date string as strict float' => ["Today", "strict float", "0.0"], + 'Arbitrary date string as strict string' => ["Today", "strict string", "'Today'"], 'Arbitrary date string as strict datetime' => ["Today", "strict datetime", "'".date_create("Today", new \DateTimezone("UTC"))->format("Y-m-d H:i:s")."'"], - 'Arbitrary date string as strict boolean' => ["Today", "strict boolean", "1"], - 'DateTime as integer' => [$dateMutable, "integer", (string) $dateUTC->getTimestamp()], - 'DateTime as float' => [$dateMutable, "float", $dateUTC->getTimestamp().".0"], - 'DateTime as string' => [$dateMutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], - 'DateTime as datetime' => [$dateMutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], - 'DateTime as boolean' => [$dateMutable, "boolean", "1"], - 'DateTime as strict integer' => [$dateMutable, "strict integer", (string) $dateUTC->getTimestamp()], - 'DateTime as strict float' => [$dateMutable, "strict float", $dateUTC->getTimestamp().".0"], - 'DateTime as strict string' => [$dateMutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], - 'DateTime as strict datetime' => [$dateMutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], - 'DateTime as strict boolean' => [$dateMutable, "strict boolean", "1"], - 'DateTimeImmutable as integer' => [$dateImmutable, "integer", (string) $dateUTC->getTimestamp()], - 'DateTimeImmutable as float' => [$dateImmutable, "float", $dateUTC->getTimestamp().".0"], - 'DateTimeImmutable as string' => [$dateImmutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], - 'DateTimeImmutable as datetime' => [$dateImmutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], - 'DateTimeImmutable as boolean' => [$dateImmutable, "boolean", "1"], - 'DateTimeImmutable as strict integer' => [$dateImmutable, "strict integer", (string) $dateUTC->getTimestamp()], - 'DateTimeImmutable as strict float' => [$dateImmutable, "strict float", $dateUTC->getTimestamp().".0"], - 'DateTimeImmutable as strict string' => [$dateImmutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], - 'DateTimeImmutable as strict datetime' => [$dateImmutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], - 'DateTimeImmutable as strict boolean' => [$dateImmutable, "strict boolean", "1"], + 'Arbitrary date string as strict boolean' => ["Today", "strict boolean", "1"], + 'DateTime as integer' => [$dateMutable, "integer", (string) $dateUTC->getTimestamp()], + 'DateTime as float' => [$dateMutable, "float", $dateUTC->getTimestamp().".0"], + 'DateTime as string' => [$dateMutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], + 'DateTime as datetime' => [$dateMutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], + 'DateTime as boolean' => [$dateMutable, "boolean", "1"], + 'DateTime as strict integer' => [$dateMutable, "strict integer", (string) $dateUTC->getTimestamp()], + 'DateTime as strict float' => [$dateMutable, "strict float", $dateUTC->getTimestamp().".0"], + 'DateTime as strict string' => [$dateMutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], + 'DateTime as strict datetime' => [$dateMutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], + 'DateTime as strict boolean' => [$dateMutable, "strict boolean", "1"], + 'DateTimeImmutable as integer' => [$dateImmutable, "integer", (string) $dateUTC->getTimestamp()], + 'DateTimeImmutable as float' => [$dateImmutable, "float", $dateUTC->getTimestamp().".0"], + 'DateTimeImmutable as string' => [$dateImmutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], + 'DateTimeImmutable as datetime' => [$dateImmutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], + 'DateTimeImmutable as boolean' => [$dateImmutable, "boolean", "1"], + 'DateTimeImmutable as strict integer' => [$dateImmutable, "strict integer", (string) $dateUTC->getTimestamp()], + 'DateTimeImmutable as strict float' => [$dateImmutable, "strict float", $dateUTC->getTimestamp().".0"], + 'DateTimeImmutable as strict string' => [$dateImmutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], + 'DateTimeImmutable as strict datetime' => [$dateImmutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], + 'DateTimeImmutable as strict boolean' => [$dateImmutable, "strict boolean", "1"], ]; - foreach ($tests as $index => list($value, $type, $exp)) { + foreach ($tests as $index => [$value, $type, $exp]) { $t = preg_replace("<^strict >", "", $type); $exp = ($exp === "null") ? $exp : $this->decorateTypeSyntax($exp, $t); yield $index => [$value, $type, $exp]; @@ -277,46 +277,46 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest { $dateImmutable = new \DateTimeImmutable("Noon Today", new \DateTimezone("America/Toronto")); $dateUTC = new \DateTime("@".$dateMutable->getTimestamp(), new \DateTimezone("UTC")); $tests = [ - 'Null as binary' => [null, "binary", "null"], - 'Null as strict binary' => [null, "strict binary", "x''"], - 'True as binary' => [true, "binary", "x'31'"], - 'True as strict binary' => [true, "strict binary", "x'31'"], - 'False as binary' => [false, "binary", "x''"], - 'False as strict binary' => [false, "strict binary", "x''"], - 'Integer as binary' => [2112, "binary", "x'32313132'"], - 'Integer as strict binary' => [2112, "strict binary", "x'32313132'"], - 'Integer zero as binary' => [0, "binary", "x'30'"], - 'Integer zero as strict binary' => [0, "strict binary", "x'30'"], - 'Float as binary' => [2112.5, "binary", "x'323131322e35'"], - 'Float as strict binary' => [2112.5, "strict binary", "x'323131322e35'"], - 'Float zero as binary' => [0.0, "binary", "x'30'"], - 'Float zero as strict binary' => [0.0, "strict binary", "x'30'"], - 'ASCII string as binary' => ["Random string", "binary", "x'52616e646f6d20737472696e67'"], - 'ASCII string as strict binary' => ["Random string", "strict binary", "x'52616e646f6d20737472696e67'"], - 'UTF-8 string as binary' => ["\u{e9}", "binary", "x'c3a9'"], - 'UTF-8 string as strict binary' => ["\u{e9}", "strict binary", "x'c3a9'"], - 'Binary string as integer' => [chr(233).chr(233), "integer", "0"], - 'Binary string as float' => [chr(233).chr(233), "float", "0.0"], - 'Binary string as string' => [chr(233).chr(233), "string", "'".chr(233).chr(233)."'"], - 'Binary string as binary' => [chr(233).chr(233), "binary", "x'e9e9'"], - 'Binary string as datetime' => [chr(233).chr(233), "datetime", "null"], - 'Binary string as boolean' => [chr(233).chr(233), "boolean", "1"], - 'Binary string as strict integer' => [chr(233).chr(233), "strict integer", "0"], - 'Binary string as strict float' => [chr(233).chr(233), "strict float", "0.0"], - 'Binary string as strict string' => [chr(233).chr(233), "strict string", "'".chr(233).chr(233)."'"], - 'Binary string as strict binary' => [chr(233).chr(233), "strict binary", "x'e9e9'"], - 'Binary string as strict datetime' => [chr(233).chr(233), "strict datetime", "'0001-01-01 00:00:00'"], - 'Binary string as strict boolean' => [chr(233).chr(233), "strict boolean", "1"], - 'ISO 8601 string as binary' => ["2017-01-09T13:11:17", "binary", "x'323031372d30312d30395431333a31313a3137'"], - 'ISO 8601 string as strict binary' => ["2017-01-09T13:11:17", "strict binary", "x'323031372d30312d30395431333a31313a3137'"], - 'Arbitrary date string as binary' => ["Today", "binary", "x'546f646179'"], + 'Null as binary' => [null, "binary", "null"], + 'Null as strict binary' => [null, "strict binary", "x''"], + 'True as binary' => [true, "binary", "x'31'"], + 'True as strict binary' => [true, "strict binary", "x'31'"], + 'False as binary' => [false, "binary", "x''"], + 'False as strict binary' => [false, "strict binary", "x''"], + 'Integer as binary' => [2112, "binary", "x'32313132'"], + 'Integer as strict binary' => [2112, "strict binary", "x'32313132'"], + 'Integer zero as binary' => [0, "binary", "x'30'"], + 'Integer zero as strict binary' => [0, "strict binary", "x'30'"], + 'Float as binary' => [2112.5, "binary", "x'323131322e35'"], + 'Float as strict binary' => [2112.5, "strict binary", "x'323131322e35'"], + 'Float zero as binary' => [0.0, "binary", "x'30'"], + 'Float zero as strict binary' => [0.0, "strict binary", "x'30'"], + 'ASCII string as binary' => ["Random string", "binary", "x'52616e646f6d20737472696e67'"], + 'ASCII string as strict binary' => ["Random string", "strict binary", "x'52616e646f6d20737472696e67'"], + 'UTF-8 string as binary' => ["\u{e9}", "binary", "x'c3a9'"], + 'UTF-8 string as strict binary' => ["\u{e9}", "strict binary", "x'c3a9'"], + 'Binary string as integer' => [chr(233).chr(233), "integer", "0"], + 'Binary string as float' => [chr(233).chr(233), "float", "0.0"], + 'Binary string as string' => [chr(233).chr(233), "string", "'".chr(233).chr(233)."'"], + 'Binary string as binary' => [chr(233).chr(233), "binary", "x'e9e9'"], + 'Binary string as datetime' => [chr(233).chr(233), "datetime", "null"], + 'Binary string as boolean' => [chr(233).chr(233), "boolean", "1"], + 'Binary string as strict integer' => [chr(233).chr(233), "strict integer", "0"], + 'Binary string as strict float' => [chr(233).chr(233), "strict float", "0.0"], + 'Binary string as strict string' => [chr(233).chr(233), "strict string", "'".chr(233).chr(233)."'"], + 'Binary string as strict binary' => [chr(233).chr(233), "strict binary", "x'e9e9'"], + 'Binary string as strict datetime' => [chr(233).chr(233), "strict datetime", "'0001-01-01 00:00:00'"], + 'Binary string as strict boolean' => [chr(233).chr(233), "strict boolean", "1"], + 'ISO 8601 string as binary' => ["2017-01-09T13:11:17", "binary", "x'323031372d30312d30395431333a31313a3137'"], + 'ISO 8601 string as strict binary' => ["2017-01-09T13:11:17", "strict binary", "x'323031372d30312d30395431333a31313a3137'"], + 'Arbitrary date string as binary' => ["Today", "binary", "x'546f646179'"], 'Arbitrary date string as strict binary' => ["Today", "strict binary", "x'546f646179'"], - 'DateTime as binary' => [$dateMutable, "binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], - 'DateTime as strict binary' => [$dateMutable, "strict binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], - 'DateTimeImmutable as binary' => [$dateImmutable, "binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], - 'DateTimeImmutable as strict binary' => [$dateImmutable, "strict binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], + 'DateTime as binary' => [$dateMutable, "binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], + 'DateTime as strict binary' => [$dateMutable, "strict binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], + 'DateTimeImmutable as binary' => [$dateImmutable, "binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], + 'DateTimeImmutable as strict binary' => [$dateImmutable, "strict binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], ]; - foreach ($tests as $index => list($value, $type, $exp)) { + foreach ($tests as $index => [$value, $type, $exp]) { $t = preg_replace("<^strict >", "", $type); $exp = ($exp === "null") ? $exp : $this->decorateTypeSyntax($exp, $t); yield $index => [$value, $type, $exp]; diff --git a/tests/cases/Db/BaseUpdate.php b/tests/cases/Db/BaseUpdate.php index 06db9db..d541513 100644 --- a/tests/cases/Db/BaseUpdate.php +++ b/tests/cases/Db/BaseUpdate.php @@ -24,7 +24,7 @@ class BaseUpdate extends \JKingWeb\Arsse\Test\AbstractTest { static::setConf(); static::$interface = static::dbInterface(); } - + public function setUp(): void { if (!static::$interface) { $this->markTestSkipped(static::$implementation." database driver not available"); diff --git a/tests/cases/Db/PostgreSQL/TestCreation.php b/tests/cases/Db/PostgreSQL/TestCreation.php index 7b3dd76..606dc8d 100644 --- a/tests/cases/Db/PostgreSQL/TestCreation.php +++ b/tests/cases/Db/PostgreSQL/TestCreation.php @@ -18,7 +18,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { $this->markTestSkipped("PostgreSQL extension not loaded"); } } - + /** @dataProvider provideConnectionStrings */ public function testGenerateConnectionString(bool $pdo, string $user, string $pass, string $db, string $host, int $port, string $service, string $exp): void { self::setConf(); diff --git a/tests/cases/Db/SQLite3/TestCreation.php b/tests/cases/Db/SQLite3/TestCreation.php index ecb942f..1a4eef9 100644 --- a/tests/cases/Db/SQLite3/TestCreation.php +++ b/tests/cases/Db/SQLite3/TestCreation.php @@ -27,8 +27,8 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { $this->files = [ // cannot create files 'Cmain' => [], - 'Cshm' => [ - 'arsse.db' => "", + 'Cshm' => [ + 'arsse.db' => "", 'arsse.db-wal' => "", ], 'Cwal' => [ @@ -36,55 +36,55 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { ], // cannot write to files 'Wmain' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Wwal' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Wshm' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], // cannot read from files 'Rmain' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Rwal' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Rshm' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], // can neither read from or write to files 'Amain' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Awal' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Ashm' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], // non-filesystem errors 'corrupt' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], diff --git a/tests/cases/Db/SQLite3PDO/TestCreation.php b/tests/cases/Db/SQLite3PDO/TestCreation.php index 50e2fe2..3b28cd5 100644 --- a/tests/cases/Db/SQLite3PDO/TestCreation.php +++ b/tests/cases/Db/SQLite3PDO/TestCreation.php @@ -29,8 +29,8 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { $this->files = [ // cannot create files 'Cmain' => [], - 'Cshm' => [ - 'arsse.db' => "", + 'Cshm' => [ + 'arsse.db' => "", 'arsse.db-wal' => "", ], 'Cwal' => [ @@ -38,55 +38,55 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { ], // cannot write to files 'Wmain' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Wwal' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Wshm' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], // cannot read from files 'Rmain' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Rwal' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Rshm' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], // can neither read from or write to files 'Amain' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Awal' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], 'Ashm' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], // non-filesystem errors 'corrupt' => [ - 'arsse.db' => "", + 'arsse.db' => "", 'arsse.db-wal' => "", 'arsse.db-shm' => "", ], diff --git a/tests/cases/Feed/TestException.php b/tests/cases/Feed/TestException.php index 8cb0f49..95adde1 100644 --- a/tests/cases/Feed/TestException.php +++ b/tests/cases/Feed/TestException.php @@ -130,7 +130,7 @@ class TestException extends \JKingWeb\Arsse\Test\AbstractTest { 408 => "timeout", 410 => "invalidUrl", 414 => "invalidUrl", - 451 => "invalidUrl" + 451 => "invalidUrl", ]; $out = array_fill(400, (600 - 400), "transmissionError"); foreach ($specials as $k => $t) { diff --git a/tests/cases/Feed/TestFeed.php b/tests/cases/Feed/TestFeed.php index c419100..01f4f5f 100644 --- a/tests/cases/Feed/TestFeed.php +++ b/tests/cases/Feed/TestFeed.php @@ -20,69 +20,69 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { protected $base = ""; protected $latest = [ [ - 'id' => 1, - 'edited' => '2000-01-01 00:00:00', - 'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda', - 'url_title_hash' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6', - 'url_content_hash' => 'fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4', + 'id' => 1, + 'edited' => '2000-01-01 00:00:00', + 'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda', + 'url_title_hash' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6', + 'url_content_hash' => 'fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4', 'title_content_hash' => '18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', ], [ - 'id' => 2, - 'edited' => '2000-01-02 00:00:00', - 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', - 'url_title_hash' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153', - 'url_content_hash' => '13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9', + 'id' => 2, + 'edited' => '2000-01-02 00:00:00', + 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', + 'url_title_hash' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153', + 'url_content_hash' => '13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9', 'title_content_hash' => '2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', ], [ - 'id' => 3, - 'edited' => '2000-01-03 00:00:00', - 'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92', - 'url_title_hash' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b', - 'url_content_hash' => 'b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406', + 'id' => 3, + 'edited' => '2000-01-03 00:00:00', + 'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92', + 'url_title_hash' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b', + 'url_content_hash' => 'b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406', 'title_content_hash' => 'ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b', ], [ - 'id' => 4, - 'edited' => '2000-01-04 00:00:00', - 'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180', - 'url_title_hash' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8', - 'url_content_hash' => 'f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3', + 'id' => 4, + 'edited' => '2000-01-04 00:00:00', + 'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180', + 'url_title_hash' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8', + 'url_content_hash' => 'f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3', 'title_content_hash' => 'ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9', ], [ - 'id' => 5, - 'edited' => '2000-01-05 00:00:00', - 'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41', - 'url_title_hash' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022', - 'url_content_hash' => '834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900', + 'id' => 5, + 'edited' => '2000-01-05 00:00:00', + 'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41', + 'url_title_hash' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022', + 'url_content_hash' => '834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900', 'title_content_hash' => '43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba', ], ]; protected $others = [ [ - 'id' => 6, - 'edited' => '2000-01-06 00:00:00', - 'guid' => 'b3461ab8e8759eeb1d65a818c65051ec00c1dfbbb32a3c8f6999434e3e3b76ab', - 'url_title_hash' => '91d051a8e6749d014506848acd45e959af50bf876427c4f0e3a1ec0f04777b51', - 'url_content_hash' => '211d78b1a040d40d17e747a363cc283f58767b2e502630d8de9b8f1d5e941d18', + 'id' => 6, + 'edited' => '2000-01-06 00:00:00', + 'guid' => 'b3461ab8e8759eeb1d65a818c65051ec00c1dfbbb32a3c8f6999434e3e3b76ab', + 'url_title_hash' => '91d051a8e6749d014506848acd45e959af50bf876427c4f0e3a1ec0f04777b51', + 'url_content_hash' => '211d78b1a040d40d17e747a363cc283f58767b2e502630d8de9b8f1d5e941d18', 'title_content_hash' => '5ed68ccb64243b8c1931241d2c9276274c3b1d87f223634aa7a1ab0141292ca7', ], [ - 'id' => 7, - 'edited' => '2000-01-07 00:00:00', - 'guid' => 'f4fae999d6531747523f4ff0c74f3f0c7c588b67e4f32d8f7dba5f6f36e8a45d', - 'url_title_hash' => 'b92f805f0d0643dad1d6c0bb5cbaec24729f5f71b37b831cf7ad31f6c9403ac8', - 'url_content_hash' => '4fc8789b787246e9be08ca1bac0d4a1ac4db1984f0db07f7142417598cf7211f', + 'id' => 7, + 'edited' => '2000-01-07 00:00:00', + 'guid' => 'f4fae999d6531747523f4ff0c74f3f0c7c588b67e4f32d8f7dba5f6f36e8a45d', + 'url_title_hash' => 'b92f805f0d0643dad1d6c0bb5cbaec24729f5f71b37b831cf7ad31f6c9403ac8', + 'url_content_hash' => '4fc8789b787246e9be08ca1bac0d4a1ac4db1984f0db07f7142417598cf7211f', 'title_content_hash' => '491df9338740b5297b3a3e8292be992ac112eb676c34595f7a38f3ee646ffe84', ], [ - 'id' => 8, - 'edited' => '2000-01-08 00:00:00', - 'guid' => 'b9d2d58e3172096b1d23b42a59961fabc89962836c3cd5de54f3d3a98ff08e6c', - 'url_title_hash' => '53a6cbcfeb66b46d09cbb7b25035df0562da35786933319c83b04be29acfb6f4', - 'url_content_hash' => 'c6f3722b4445b49d19d39c3bf5b11a7cf23dd69873e2a0a458aab662f1cd9438', + 'id' => 8, + 'edited' => '2000-01-08 00:00:00', + 'guid' => 'b9d2d58e3172096b1d23b42a59961fabc89962836c3cd5de54f3d3a98ff08e6c', + 'url_title_hash' => '53a6cbcfeb66b46d09cbb7b25035df0562da35786933319c83b04be29acfb6f4', + 'url_content_hash' => 'c6f3722b4445b49d19d39c3bf5b11a7cf23dd69873e2a0a458aab662f1cd9438', 'title_content_hash' => '607d2da48807ca984ce2a9faa1d291bd9e3de9e912f83306167f4f5cd3c23bbd', ], ]; @@ -209,10 +209,10 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { public function provide304ResponseURLs() { return [ - 'Control' => ["Caching/304Conditional"], - 'Random last-mod and ETag' => ["Caching/304Random"], - 'ETag only' => ["Caching/304ETagOnly"], - 'Last-mod only' => ["Caching/304LastModOnly"], + 'Control' => ["Caching/304Conditional"], + 'Random last-mod and ETag' => ["Caching/304Random"], + 'ETag only' => ["Caching/304ETagOnly"], + 'Last-mod only' => ["Caching/304LastModOnly"], 'Neither last-mod nor ETag' => ["Caching/304None"], ]; } @@ -267,16 +267,16 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { public function provide304Timestamps(): iterable { return [ - 'less than half an hour 1' => ["now", "now + 15 minutes"], - 'less than half an hour 2' => ["now - 29 minutes", "now + 15 minutes"], - 'less than one hour 1' => ["now - 30 minutes", "now + 30 minutes"], - 'less than one hour 2' => ["now - 59 minutes", "now + 30 minutes"], - 'less than three hours 1' => ["now - 1 hour", "now + 1 hour"], - 'less than three hours 2' => ["now - 2 hours 59 minutes", "now + 1 hour"], + 'less than half an hour 1' => ["now", "now + 15 minutes"], + 'less than half an hour 2' => ["now - 29 minutes", "now + 15 minutes"], + 'less than one hour 1' => ["now - 30 minutes", "now + 30 minutes"], + 'less than one hour 2' => ["now - 59 minutes", "now + 30 minutes"], + 'less than three hours 1' => ["now - 1 hour", "now + 1 hour"], + 'less than three hours 2' => ["now - 2 hours 59 minutes", "now + 1 hour"], 'more than thirty-six hours 1' => ["now - 36 hours", "now + 1 day"], 'more than thirty-six hours 2' => ["now - 2 years", "now + 1 day"], - 'fallback 1' => ["now - 3 hours", "now + 3 hours"], - 'fallback 2' => ["now - 35 hours", "now + 3 hours"], + 'fallback 1' => ["now - 3 hours", "now + 3 hours"], + 'fallback 2' => ["now - 35 hours", "now + 3 hours"], ]; } diff --git a/tests/cases/ImportExport/TestImportExport.php b/tests/cases/ImportExport/TestImportExport.php index ee8830c..4d3fef3 100644 --- a/tests/cases/ImportExport/TestImportExport.php +++ b/tests/cases/ImportExport/TestImportExport.php @@ -117,9 +117,9 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ], 'arsse_tag_members' => [ 'columns' => [ - 'tag' => "int", + 'tag' => "int", 'subscription' => "int", - 'assigned' => "bool", + 'assigned' => "bool", ], 'rows' => [ [1, 2, 1], @@ -181,7 +181,7 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ['url' => "http://localhost:8000/Import/citizen", 'title' => "Ottawa Citizen", 'folder' => 6, 'tags' => ["news", "canada"]], ['url' => "http://localhost:8000/Import/eurogamer", 'title' => "Eurogamer", 'folder' => 0, 'tags' => ["gaming", "frequent"]], ['url' => "http://localhost:8000/Import/cbc", 'title' => "CBC News", 'folder' => 6, 'tags' => ["news", "canada"]], - ], [1 => + ], [1 => ['id' => 1, 'name' => "Photography", 'parent' => 0], ['id' => 2, 'name' => "Science", 'parent' => 0], ['id' => 3, 'name' => "Rocketry", 'parent' => 2], @@ -205,7 +205,7 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ['url' => "http://localhost:8000/Import/citizen", 'title' => "Ottawa Citizen", 'folder' => 6, 'tags' => ["news", "canada"]], ['url' => "http://localhost:8000/Import/eurogamer", 'title' => "Eurogamer", 'folder' => 0, 'tags' => ["gaming", "frequent"]], ['url' => "http://localhost:8000/Import/cbc", 'title' => "CBC", 'folder' => 0, 'tags' => ["news", "canada"]], // moved to root and renamed - ], [1 => + ], [1 => ['id' => 1, 'name' => "Photography", 'parent' => 0], ['id' => 2, 'name' => "Science", 'parent' => 0], ['id' => 3, 'name' => "Rocketry", 'parent' => 2], diff --git a/tests/cases/ImportExport/TestOPML.php b/tests/cases/ImportExport/TestOPML.php index 234d6b5..1e65fa1 100644 --- a/tests/cases/ImportExport/TestOPML.php +++ b/tests/cases/ImportExport/TestOPML.php @@ -152,7 +152,7 @@ OPML_EXPORT_SERIALIZATION; ['url' => "https://www.thestar.com/content/thestar/feed.RSSManagerServlet.topstories.rss", 'title' => "Toronto Star", 'folder' => 5, 'tags' => ["news", "canada", "toronto"]], ['url' => "http://rss.canada.com/get/?F239", 'title' => "Ottawa Citizen", 'folder' => 6, 'tags' => ["news", "canada"]], ['url' => "https://www.eurogamer.net/?format=rss", 'title' => "Eurogamer", 'folder' => 0, 'tags' => ["gaming", "frequent"]], - ], [1 => + ], [1 => ['id' => 1, 'name' => "Photography", 'parent' => 0], ['id' => 2, 'name' => "Science", 'parent' => 0], ['id' => 3, 'name' => "Rocketry", 'parent' => 2], diff --git a/tests/cases/Misc/TestContext.php b/tests/cases/Misc/TestContext.php index b4f51c5..037ca8e 100644 --- a/tests/cases/Misc/TestContext.php +++ b/tests/cases/Misc/TestContext.php @@ -25,44 +25,44 @@ class TestContext extends \JKingWeb\Arsse\Test\AbstractTest { public function testSetContextOptions(): void { $v = [ - 'reverse' => true, - 'limit' => 10, - 'offset' => 5, - 'folder' => 42, - 'folders' => [12,22], - 'folderShallow' => 42, - 'foldersShallow' => [0,1], - 'tag' => 44, - 'tags' => [44, 2112], - 'tagName' => "XLIV", - 'tagNames' => ["XLIV", "MMCXII"], - 'subscription' => 2112, - 'subscriptions' => [44, 2112], - 'article' => 255, - 'edition' => 65535, - 'latestArticle' => 47, - 'oldestArticle' => 1337, - 'latestEdition' => 47, - 'oldestEdition' => 1337, - 'unread' => true, - 'starred' => true, - 'modifiedSince' => new \DateTime(), + 'reverse' => true, + 'limit' => 10, + 'offset' => 5, + 'folder' => 42, + 'folders' => [12,22], + 'folderShallow' => 42, + 'foldersShallow' => [0,1], + 'tag' => 44, + 'tags' => [44, 2112], + 'tagName' => "XLIV", + 'tagNames' => ["XLIV", "MMCXII"], + 'subscription' => 2112, + 'subscriptions' => [44, 2112], + 'article' => 255, + 'edition' => 65535, + 'latestArticle' => 47, + 'oldestArticle' => 1337, + 'latestEdition' => 47, + 'oldestEdition' => 1337, + 'unread' => true, + 'starred' => true, + 'modifiedSince' => new \DateTime(), 'notModifiedSince' => new \DateTime(), - 'markedSince' => new \DateTime(), - 'notMarkedSince' => new \DateTime(), - 'editions' => [1,2], - 'articles' => [1,2], - 'label' => 2112, - 'labels' => [2112, 1984], - 'labelName' => "Rush", - 'labelNames' => ["Rush", "Orwell"], - 'labelled' => true, - 'annotated' => true, - 'searchTerms' => ["foo", "bar"], - 'annotationTerms' => ["foo", "bar"], - 'titleTerms' => ["foo", "bar"], - 'authorTerms' => ["foo", "bar"], - 'not' => (new Context)->subscription(5), + 'markedSince' => new \DateTime(), + 'notMarkedSince' => new \DateTime(), + 'editions' => [1,2], + 'articles' => [1,2], + 'label' => 2112, + 'labels' => [2112, 1984], + 'labelName' => "Rush", + 'labelNames' => ["Rush", "Orwell"], + 'labelled' => true, + 'annotated' => true, + 'searchTerms' => ["foo", "bar"], + 'annotationTerms' => ["foo", "bar"], + 'titleTerms' => ["foo", "bar"], + 'authorTerms' => ["foo", "bar"], + 'not' => (new Context)->subscription(5), ]; $times = ['modifiedSince','notModifiedSince','markedSince','notMarkedSince']; $c = new Context; diff --git a/tests/cases/Misc/TestHTTP.php b/tests/cases/Misc/TestHTTP.php index 04199d1..9bffe07 100644 --- a/tests/cases/Misc/TestHTTP.php +++ b/tests/cases/Misc/TestHTTP.php @@ -7,7 +7,6 @@ declare(strict_types=1); namespace JKingWeb\Arsse\TestCase\Misc; use JKingWeb\Arsse\Misc\HTTP; -use Psr\Http\Message\ResponseInterface; /** @covers \JKingWeb\Arsse\Misc\HTTP */ class TestHTTP extends \JKingWeb\Arsse\Test\AbstractTest { diff --git a/tests/cases/Misc/TestQuery.php b/tests/cases/Misc/TestQuery.php index 7d94f90..db8a629 100644 --- a/tests/cases/Misc/TestQuery.php +++ b/tests/cases/Misc/TestQuery.php @@ -7,7 +7,6 @@ declare(strict_types=1); namespace JKingWeb\Arsse\TestCase\Misc; use JKingWeb\Arsse\Misc\Query; -use JKingWeb\Arsse\Misc\ValueInfo; /** @covers \JKingWeb\Arsse\Misc\Query */ class TestQuery extends \JKingWeb\Arsse\Test\AbstractTest { diff --git a/tests/cases/Misc/TestURL.php b/tests/cases/Misc/TestURL.php index 46f5886..52bafa4 100644 --- a/tests/cases/Misc/TestURL.php +++ b/tests/cases/Misc/TestURL.php @@ -13,7 +13,7 @@ class TestURL extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp(): void { self::clearData(); } - + /** @dataProvider provideNormalizations */ public function testNormalizeAUrl(string $url, string $exp, string $user = null, string $pass = null): void { $this->assertSame($exp, URL::normalize($url, $user, $pass)); diff --git a/tests/cases/Misc/TestValueInfo.php b/tests/cases/Misc/TestValueInfo.php index a35040b..6a4c6ba 100644 --- a/tests/cases/Misc/TestValueInfo.php +++ b/tests/cases/Misc/TestValueInfo.php @@ -87,7 +87,7 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { [" 1 ", I::VALID], ]; foreach ($tests as $test) { - list($value, $exp) = $test; + [$value, $exp] = $test; $this->assertSame($exp, I::int($value), "Test returned ".decbin(I::int($value))." for value: ".var_export($value, true)); } } @@ -157,7 +157,7 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { [new StrClass(" "), I::VALID | I::WHITE], ]; foreach ($tests as $test) { - list($value, $exp) = $test; + [$value, $exp] = $test; $this->assertSame($exp, I::str($value), "Test returned ".decbin(I::str($value))." for value: ".var_export($value, true)); } } @@ -228,7 +228,7 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { [new StrClass(" "), false, false], ]; foreach ($tests as $test) { - list($value, $exp, $expNull) = $test; + [$value, $exp, $expNull] = $test; $this->assertSame($exp, I::id($value), "Non-null test failed for value: ".var_export($value, true)); $this->assertSame($expNull, I::id($value, true), "Null test failed for value: ".var_export($value, true)); } @@ -300,7 +300,7 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { [new StrClass(" "), null], ]; foreach ($tests as $test) { - list($value, $exp) = $test; + [$value, $exp] = $test; $this->assertSame($exp, I::bool($value), "Null Test failed for value: ".var_export($value, true)); if (is_null($exp)) { $this->assertTrue(I::bool($value, true), "True Test failed for value: ".var_export($value, true)); @@ -400,14 +400,14 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { public function testNormalizeComplexValues(): void { // Array-mode tests $tests = [ - [I::T_INT | I::M_DROP, [1, 2, 2.2, 3], [1,2,null,3] ], + [I::T_INT | I::M_DROP, [1, 2, 2.2, 3], [1,2,null,3] ], [I::T_INT, [1, 2, 2.2, 3], [1,2,2,3] ], - [I::T_INT | I::M_DROP, new Result([1, 2, 2.2, 3]), [1,2,null,3] ], + [I::T_INT | I::M_DROP, new Result([1, 2, 2.2, 3]), [1,2,null,3] ], [I::T_INT, new Result([1, 2, 2.2, 3]), [1,2,2,3] ], [I::T_STRING | I::M_STRICT, "Bare string", ["Bare string"]], ]; foreach ($tests as $index => $test) { - list($type, $value, $exp) = $test; + [$type, $value, $exp] = $test; $this->assertEquals($exp, I::normalize($value, $type | I::M_ARRAY, "iso8601"), "Failed test #$index"); } // Date-to-string format tests @@ -525,15 +525,15 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { [$this->d("2010-01-01T00:00:00", 0, 1), [null,true], [true, false], [1262304000, false], [1262304000.0, false], ["2010-01-01T00:00:00Z",true], [[$this->d("2010-01-01T00:00:00", 0, 1)],false], [null, false]], [$this->d("2010-01-01T00:00:00", 1, 0), [null,true], [true, false], [1262322000, false], [1262322000.0, false], ["2010-01-01T05:00:00Z",true], [[$this->d("2010-01-01T00:00:00", 1, 0)],false], [null, false]], [$this->d("2010-01-01T00:00:00", 1, 1), [null,true], [true, false], [1262322000, false], [1262322000.0, false], ["2010-01-01T05:00:00Z",true], [[$this->d("2010-01-01T00:00:00", 1, 1)],false], [null, false]], - [1e14, [null,true], [true, false], [pow(10, 14), true], [1e14, true], ["100000000000000", true], [[1e14], false], [$this->i("P1157407407DT9H46M40S"), false]], + [1e14, [null,true], [true, false], [10 ** 14, true], [1e14, true], ["100000000000000", true], [[1e14], false], [$this->i("P1157407407DT9H46M40S"), false]], [1e-6, [null,true], [true, false], [0, false], [1e-6, true], ["0.000001", true], [[1e-6], false], [$this->i("PT0S", 1e-6), false]], [[1,2,3], [null,true], [true, false], [0, false], [0.0, false], ["", false], [[1,2,3], true], [null, false]], - [['a'=>1,'b'=>2], [null,true], [true, false], [0, false], [0.0, false], ["", false], [['a'=>1,'b'=>2], true], [null, false]], - [new Result([['a'=>1,'b'=>2]]), [null,true], [true, false], [0, false], [0.0, false], ["", false], [[['a'=>1,'b'=>2]], true], [null, false]], - [$this->i("PT1H"), [null,true], [true, false], [60*60, false], [60.0*60.0, false], ["PT1H", true], [[$this->i("PT1H")], false], [$this->i("PT1H"), true]], - [$this->i("P2DT1H"), [null,true], [true, false], [(48+1)*60*60, false], [1.0*(48+1)*60*60, false], ["P2DT1H", true], [[$this->i("P2DT1H")], false], [$this->i("P2DT1H"), true]], + [['a' => 1,'b' => 2], [null,true], [true, false], [0, false], [0.0, false], ["", false], [['a' => 1,'b' => 2], true], [null, false]], + [new Result([['a' => 1,'b' => 2]]), [null,true], [true, false], [0, false], [0.0, false], ["", false], [[['a' => 1,'b' => 2]], true], [null, false]], + [$this->i("PT1H"), [null,true], [true, false], [60 * 60, false], [60.0 * 60.0, false], ["PT1H", true], [[$this->i("PT1H")], false], [$this->i("PT1H"), true]], + [$this->i("P2DT1H"), [null,true], [true, false], [(48 + 1) * 60 * 60, false], [1.0 * (48 + 1) * 60 * 60, false], ["P2DT1H", true], [[$this->i("P2DT1H")], false], [$this->i("P2DT1H"), true]], [$this->i("PT0H"), [null,true], [true, false], [0, false], [0.0, false], ["PT0S", true], [[$this->i("PT0H")], false], [$this->i("PT0H"), true]], - [$dateDiff, [null,true], [true, false], [366*24*60*60, false], [1.0*366*24*60*60, false], ["P366D", true], [[$dateDiff], false], [$dateNorm, true]], + [$dateDiff, [null,true], [true, false], [366 * 24 * 60 * 60, false], [1.0 * 366 * 24 * 60 * 60, false], ["P366D", true], [[$dateDiff], false], [$dateNorm, true]], ["1 year, 2 days", [null,true], [true, false], [0, false], [0.0, false], ["1 year, 2 days", true], [["1 year, 2 days"], false], [$this->i("P1Y2D"), false]], ["P1Y2D", [null,true], [true, false], [0, false], [0.0, false], ["P1Y2D", true], [["P1Y2D"], false], [$this->i("P1Y2D"), true]], ] as $set) { @@ -542,14 +542,14 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { // shift a mixed-type passthrough test onto the set array_unshift($set, [$input, true]); // generate a set of tests for each target data type - foreach ($set as $type => list($exp, $pass)) { + foreach ($set as $type => [$exp, $pass]) { // emit one test each for loose mode, strict mode, drop mode, and strict+drop mode foreach ([ [false, false], [true, false], [false, true], [true, true], - ] as list($strict, $drop)) { + ] as [$strict, $drop]) { yield [$input, $types[$type], $exp, $pass, $strict, $drop]; } } @@ -572,37 +572,37 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { ]; foreach ([ /* Input value microtime iso8601 iso8601m http sql date time unix float '!M j, Y (D)' *strtotime* (null) */ - [null, null, null, null, null, null, null, null, null, null, null, null, ], - [INF, null, null, null, null, null, null, null, null, null, null, null, ], - [NAN, null, null, null, null, null, null, null, null, null, null, null, ], - [$this->d("2010-01-01T00:00:00", 0, 0), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), ], - [$this->d("2010-01-01T00:00:00", 0, 1), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), ], - [$this->d("2010-01-01T00:00:00", 1, 0), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), ], - [$this->d("2010-01-01T00:00:00", 1, 1), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), ], - [1262304000, $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), ], - [1262304000.123456, $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), ], - [1262304000.42, $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), ], - ["0.12345600 1262304000", $this->t(1262304000.123456), null, null, null, null, null, null, null, null, null, null, ], - ["0.42 1262304000", null, null, null, null, null, null, null, null, null, null, null, ], - ["2010-01-01T00:00:00", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000), ], - ["2010-01-01T00:00:00Z", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000), ], - ["2010-01-01T00:00:00+0000", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000), ], - ["2010-01-01T00:00:00-0000", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000), ], - ["2010-01-01T00:00:00+00:00", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000), ], - ["2010-01-01T00:00:00-05:00", null, $this->t(1262322000), $this->t(1262322000), null, null, null, null, null, null, null, $this->t(1262322000), ], - ["2010-01-01T00:00:00.123456Z", null, null, $this->t(1262304000.123456), null, null, null, null, null, null, null, $this->t(1262304000.123456), ], - ["Fri, 01 Jan 2010 00:00:00 GMT", null, null, null, $this->t(1262304000), null, null, null, null, null, null, $this->t(1262304000), ], - ["2010-01-01 00:00:00", null, null, null, null, $this->t(1262304000), null, null, null, null, null, $this->t(1262304000), ], - ["2010-01-01", null, null, null, null, null, $this->t(1262304000), null, null, null, null, $this->t(1262304000), ], - ["12:34:56", null, null, null, null, null, null, $this->t(45296), null, null, null, $this->t(date_create("today", new \DateTimezone("UTC"))->getTimestamp()+45296), ], - ["1262304000", null, null, null, null, null, null, null, $this->t(1262304000), null, null, null, ], - ["1262304000.123456", null, null, null, null, null, null, null, null, $this->t(1262304000.123456), null, null, ], - ["1262304000.42", null, null, null, null, null, null, null, null, $this->t(1262304000.42), null, null, ], - ["Jan 1, 2010 (Fri)", null, null, null, null, null, null, null, null, null, $this->t(1262304000), null, ], - ["First day of Jan 2010 12AM", null, null, null, null, null, null, null, null, null, null, $this->t(1262304000), ], - [[], null, null, null, null, null, null, null, null, null, null, null, ], - [$this->i("P1Y2D"), null, null, null, null, null, null, null, null, null, null, null, ], - ["P1Y2D", null, null, null, null, null, null, null, null, null, null, null, ], + [null, null, null, null, null, null, null, null, null, null, null, null], + [INF, null, null, null, null, null, null, null, null, null, null, null], + [NAN, null, null, null, null, null, null, null, null, null, null, null], + [$this->d("2010-01-01T00:00:00", 0, 0), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000)], + [$this->d("2010-01-01T00:00:00", 0, 1), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000)], + [$this->d("2010-01-01T00:00:00", 1, 0), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000)], + [$this->d("2010-01-01T00:00:00", 1, 1), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000), $this->t(1262322000)], + [1262304000, $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000), $this->t(1262304000)], + [1262304000.123456, $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456), $this->t(1262304000.123456)], + [1262304000.42, $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42), $this->t(1262304000.42)], + ["0.12345600 1262304000", $this->t(1262304000.123456), null, null, null, null, null, null, null, null, null, null], + ["0.42 1262304000", null, null, null, null, null, null, null, null, null, null, null], + ["2010-01-01T00:00:00", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000)], + ["2010-01-01T00:00:00Z", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000)], + ["2010-01-01T00:00:00+0000", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000)], + ["2010-01-01T00:00:00-0000", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000)], + ["2010-01-01T00:00:00+00:00", null, $this->t(1262304000), $this->t(1262304000), null, null, null, null, null, null, null, $this->t(1262304000)], + ["2010-01-01T00:00:00-05:00", null, $this->t(1262322000), $this->t(1262322000), null, null, null, null, null, null, null, $this->t(1262322000)], + ["2010-01-01T00:00:00.123456Z", null, null, $this->t(1262304000.123456), null, null, null, null, null, null, null, $this->t(1262304000.123456)], + ["Fri, 01 Jan 2010 00:00:00 GMT", null, null, null, $this->t(1262304000), null, null, null, null, null, null, $this->t(1262304000)], + ["2010-01-01 00:00:00", null, null, null, null, $this->t(1262304000), null, null, null, null, null, $this->t(1262304000)], + ["2010-01-01", null, null, null, null, null, $this->t(1262304000), null, null, null, null, $this->t(1262304000)], + ["12:34:56", null, null, null, null, null, null, $this->t(45296), null, null, null, $this->t(date_create("today", new \DateTimezone("UTC"))->getTimestamp() + 45296)], + ["1262304000", null, null, null, null, null, null, null, $this->t(1262304000), null, null, null], + ["1262304000.123456", null, null, null, null, null, null, null, null, $this->t(1262304000.123456), null, null], + ["1262304000.42", null, null, null, null, null, null, null, null, $this->t(1262304000.42), null, null], + ["Jan 1, 2010 (Fri)", null, null, null, null, null, null, null, null, null, $this->t(1262304000), null], + ["First day of Jan 2010 12AM", null, null, null, null, null, null, null, null, null, null, $this->t(1262304000)], + [[], null, null, null, null, null, null, null, null, null, null, null], + [$this->i("P1Y2D"), null, null, null, null, null, null, null, null, null, null, null], + ["P1Y2D", null, null, null, null, null, null, null, null, null, null, null], ] as $set) { // shift the input value off the set $input = array_shift($set); @@ -614,7 +614,7 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { [true, false], [false, true], [true, true], - ] as list($strict, $drop)) { + ] as [$strict, $drop]) { yield [$input, $formats[$format], $exp, $strict, $drop]; } } diff --git a/tests/cases/REST/Fever/TestAPI.php b/tests/cases/REST/Fever/TestAPI.php index 6bdce39..f65de41 100644 --- a/tests/cases/REST/Fever/TestAPI.php +++ b/tests/cases/REST/Fever/TestAPI.php @@ -28,115 +28,115 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { protected $articles = [ 'db' => [ [ - 'id' => 101, - 'url' => 'http://example.com/1', - 'title' => 'Article title 1', - 'author' => '', - 'content' => '

Article content 1

', + 'id' => 101, + 'url' => 'http://example.com/1', + 'title' => 'Article title 1', + 'author' => '', + 'content' => '

Article content 1

', 'published_date' => '2000-01-01 00:00:00', - 'unread' => 1, - 'starred' => 0, - 'subscription' => 8, + 'unread' => 1, + 'starred' => 0, + 'subscription' => 8, ], [ - 'id' => 102, - 'url' => 'http://example.com/2', - 'title' => 'Article title 2', - 'author' => '', - 'content' => '

Article content 2

', + 'id' => 102, + 'url' => 'http://example.com/2', + 'title' => 'Article title 2', + 'author' => '', + 'content' => '

Article content 2

', 'published_date' => '2000-01-02 00:00:00', - 'unread' => 0, - 'starred' => 0, - 'subscription' => 8, + 'unread' => 0, + 'starred' => 0, + 'subscription' => 8, ], [ - 'id' => 103, - 'url' => 'http://example.com/3', - 'title' => 'Article title 3', - 'author' => '', - 'content' => '

Article content 3

', + 'id' => 103, + 'url' => 'http://example.com/3', + 'title' => 'Article title 3', + 'author' => '', + 'content' => '

Article content 3

', 'published_date' => '2000-01-03 00:00:00', - 'unread' => 1, - 'starred' => 1, - 'subscription' => 9, + 'unread' => 1, + 'starred' => 1, + 'subscription' => 9, ], [ - 'id' => 104, - 'url' => 'http://example.com/4', - 'title' => 'Article title 4', - 'author' => '', - 'content' => '

Article content 4

', + 'id' => 104, + 'url' => 'http://example.com/4', + 'title' => 'Article title 4', + 'author' => '', + 'content' => '

Article content 4

', 'published_date' => '2000-01-04 00:00:00', - 'unread' => 0, - 'starred' => 1, - 'subscription' => 9, + 'unread' => 0, + 'starred' => 1, + 'subscription' => 9, ], [ - 'id' => 105, - 'url' => 'http://example.com/5', - 'title' => 'Article title 5', - 'author' => '', - 'content' => '

Article content 5

', + 'id' => 105, + 'url' => 'http://example.com/5', + 'title' => 'Article title 5', + 'author' => '', + 'content' => '

Article content 5

', 'published_date' => '2000-01-05 00:00:00', - 'unread' => 1, - 'starred' => 0, - 'subscription' => 10, + 'unread' => 1, + 'starred' => 0, + 'subscription' => 10, ], ], 'rest' => [ [ - 'id' => 101, - 'feed_id' => 8, - 'title' => 'Article title 1', - 'author' => '', - 'html' => '

Article content 1

', - 'url' => 'http://example.com/1', - 'is_saved' => 0, - 'is_read' => 0, + 'id' => 101, + 'feed_id' => 8, + 'title' => 'Article title 1', + 'author' => '', + 'html' => '

Article content 1

', + 'url' => 'http://example.com/1', + 'is_saved' => 0, + 'is_read' => 0, 'created_on_time' => 946684800, ], [ - 'id' => 102, - 'feed_id' => 8, - 'title' => 'Article title 2', - 'author' => '', - 'html' => '

Article content 2

', - 'url' => 'http://example.com/2', - 'is_saved' => 0, - 'is_read' => 1, + 'id' => 102, + 'feed_id' => 8, + 'title' => 'Article title 2', + 'author' => '', + 'html' => '

Article content 2

', + 'url' => 'http://example.com/2', + 'is_saved' => 0, + 'is_read' => 1, 'created_on_time' => 946771200, ], [ - 'id' => 103, - 'feed_id' => 9, - 'title' => 'Article title 3', - 'author' => '', - 'html' => '

Article content 3

', - 'url' => 'http://example.com/3', - 'is_saved' => 1, - 'is_read' => 0, + 'id' => 103, + 'feed_id' => 9, + 'title' => 'Article title 3', + 'author' => '', + 'html' => '

Article content 3

', + 'url' => 'http://example.com/3', + 'is_saved' => 1, + 'is_read' => 0, 'created_on_time' => 946857600, ], [ - 'id' => 104, - 'feed_id' => 9, - 'title' => 'Article title 4', - 'author' => '', - 'html' => '

Article content 4

', - 'url' => 'http://example.com/4', - 'is_saved' => 1, - 'is_read' => 1, + 'id' => 104, + 'feed_id' => 9, + 'title' => 'Article title 4', + 'author' => '', + 'html' => '

Article content 4

', + 'url' => 'http://example.com/4', + 'is_saved' => 1, + 'is_read' => 1, 'created_on_time' => 946944000, ], [ - 'id' => 105, - 'feed_id' => 10, - 'title' => 'Article title 5', - 'author' => '', - 'html' => '

Article content 5

', - 'url' => 'http://example.com/5', - 'is_saved' => 0, - 'is_read' => 0, + 'id' => 105, + 'feed_id' => 10, + 'title' => 'Article title 5', + 'author' => '', + 'html' => '

Article content 5

', + 'url' => 'http://example.com/5', + 'is_saved' => 0, + 'is_read' => 0, 'created_on_time' => 947030400, ], ], @@ -176,7 +176,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { public function testAuthenticateAUserToken(bool $httpRequired, bool $tokenEnforced, string $httpUser = null, array $dataPost, array $dataGet, ResponseInterface $exp): void { self::setConf([ 'userHTTPAuthRequired' => $httpRequired, - 'userSessionEnforced' => $tokenEnforced, + 'userSessionEnforced' => $tokenEnforced, ], true); Arsse::$user->id = null; \Phake::when(Arsse::$db)->tokenLookup->thenThrow(new ExceptionInput("subjectMissing")); @@ -305,7 +305,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { \Phake::when(Arsse::$db)->articleList->thenReturn(new Result($this->articles['db'])); \Phake::when(Arsse::$db)->articleCount(Arsse::$user->id)->thenReturn(1024); $exp = new JsonResponse([ - 'items' => $this->articles['rest'], + 'items' => $this->articles['rest'], 'total_items' => 1024, ]); $act = $this->h->dispatch($this->req("api&$url")); @@ -334,21 +334,15 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { $unread = [['id' => 4],['id' => 5],['id' => 6]]; \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->starred(true))->thenReturn(new Result($saved)); \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->unread(true))->thenReturn(new Result($unread)); - $exp = new JsonResponse([ - 'saved_item_ids' => "1,2,3" - ]); + $exp = new JsonResponse(['saved_item_ids' => "1,2,3"]); $this->assertMessage($exp, $this->h->dispatch($this->req("api&saved_item_ids"))); - $exp = new JsonResponse([ - 'unread_item_ids' => "4,5,6" - ]); + $exp = new JsonResponse(['unread_item_ids' => "4,5,6"]); $this->assertMessage($exp, $this->h->dispatch($this->req("api&unread_item_ids"))); } public function testListHotLinks(): void { // hot links are not actually implemented, so an empty array should be all we get - $exp = new JsonResponse([ - 'links' => [] - ]); + $exp = new JsonResponse(['links' => []]); $this->assertMessage($exp, $this->h->dispatch($this->req("api&links"))); } @@ -444,16 +438,16 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { \Phake::when($this->h)->logIn->thenReturn(true); \Phake::when(Arsse::$db)->subscriptionRefreshed(Arsse::$user->id)->thenReturn(new \DateTimeImmutable("2000-01-01T00:00:00Z")); $exp = new JsonResponse([ - 'api_version' => API::LEVEL, - 'auth' => 1, + 'api_version' => API::LEVEL, + 'auth' => 1, 'last_refreshed_on_time' => 946684800, ]); $act = $this->h->dispatch($this->req("api")); $this->assertMessage($exp, $act); \Phake::when(Arsse::$db)->subscriptionRefreshed(Arsse::$user->id)->thenReturn(null); // no subscriptions $exp = new JsonResponse([ - 'api_version' => API::LEVEL, - 'auth' => 1, + 'api_version' => API::LEVEL, + 'auth' => 1, 'last_refreshed_on_time' => null, ]); $act = $this->h->dispatch($this->req("api")); @@ -461,7 +455,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { \Phake::when($this->h)->logIn->thenReturn(false); $exp = new JsonResponse([ 'api_version' => API::LEVEL, - 'auth' => 0, + 'auth' => 0, ]); $act = $this->h->dispatch($this->req("api")); $this->assertMessage($exp, $act); @@ -485,7 +479,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { public function testOutputToXml(): void { \Phake::when($this->h)->processRequest->thenReturn([ - 'items' => $this->articles['rest'], + 'items' => $this->articles['rest'], 'total_items' => 1024, ]); $exp = new XmlResponse("1018Article title 1<p>Article content 1</p>http://example.com/1009466848001028Article title 2<p>Article content 2</p>http://example.com/2019467712001039Article title 3<p>Article content 3</p>http://example.com/3109468576001049Article title 4<p>Article content 4</p>http://example.com/41194694400010510Article title 5<p>Article content 5</p>http://example.com/5009470304001024"); @@ -502,7 +496,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { public function testAnswerOptionsRequest(): void { $act = $this->h->dispatch($this->req("api", "", "OPTIONS")); $exp = new EmptyResponse(204, [ - 'Allow' => "POST", + 'Allow' => "POST", 'Accept' => "application/x-www-form-urlencoded", ]); $this->assertMessage($exp, $act); diff --git a/tests/cases/REST/NextcloudNews/TestV1_2.php b/tests/cases/REST/NextcloudNews/TestV1_2.php index dfe3008..5e8c7d1 100644 --- a/tests/cases/REST/NextcloudNews/TestV1_2.php +++ b/tests/cases/REST/NextcloudNews/TestV1_2.php @@ -26,274 +26,274 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { protected $feeds = [ // expected sample output of a feed list from the database, and the resultant expected transformation by the REST handler 'db' => [ [ - 'id' => 2112, - 'url' => 'http://example.com/news.atom', - 'favicon' => 'http://example.com/favicon.png', - 'source' => 'http://example.com/', - 'folder' => null, + 'id' => 2112, + 'url' => 'http://example.com/news.atom', + 'favicon' => 'http://example.com/favicon.png', + 'source' => 'http://example.com/', + 'folder' => null, 'top_folder' => null, - 'pinned' => 0, - 'err_count' => 0, - 'err_msg' => '', + 'pinned' => 0, + 'err_count' => 0, + 'err_msg' => '', 'order_type' => 0, - 'added' => '2017-05-20 13:35:54', - 'title' => 'First example feed', - 'unread' => 50048, + 'added' => '2017-05-20 13:35:54', + 'title' => 'First example feed', + 'unread' => 50048, ], [ - 'id' => 42, - 'url' => 'http://example.org/news.atom', - 'favicon' => 'http://example.org/favicon.png', - 'source' => 'http://example.org/', - 'folder' => 12, + 'id' => 42, + 'url' => 'http://example.org/news.atom', + 'favicon' => 'http://example.org/favicon.png', + 'source' => 'http://example.org/', + 'folder' => 12, 'top_folder' => 8, - 'pinned' => 1, - 'err_count' => 0, - 'err_msg' => '', + 'pinned' => 1, + 'err_count' => 0, + 'err_msg' => '', 'order_type' => 2, - 'added' => '2017-05-20 13:35:54', - 'title' => 'Second example feed', - 'unread' => 23, + 'added' => '2017-05-20 13:35:54', + 'title' => 'Second example feed', + 'unread' => 23, ], [ - 'id' => 47, - 'url' => 'http://example.net/news.atom', - 'favicon' => 'http://example.net/favicon.png', - 'source' => 'http://example.net/', - 'folder' => null, + 'id' => 47, + 'url' => 'http://example.net/news.atom', + 'favicon' => 'http://example.net/favicon.png', + 'source' => 'http://example.net/', + 'folder' => null, 'top_folder' => null, - 'pinned' => 0, - 'err_count' => 0, - 'err_msg' => null, + 'pinned' => 0, + 'err_count' => 0, + 'err_msg' => null, 'order_type' => 1, - 'added' => '2017-05-20 13:35:54', - 'title' => 'Third example feed', - 'unread' => 0, + 'added' => '2017-05-20 13:35:54', + 'title' => 'Third example feed', + 'unread' => 0, ], ], 'rest' => [ [ - 'id' => 2112, - 'url' => 'http://example.com/news.atom', - 'title' => 'First example feed', - 'added' => 1495287354, - 'pinned' => false, - 'link' => 'http://example.com/', - 'faviconLink' => 'http://example.com/favicon.png', - 'folderId' => 0, - 'unreadCount' => 50048, - 'ordering' => 0, + 'id' => 2112, + 'url' => 'http://example.com/news.atom', + 'title' => 'First example feed', + 'added' => 1495287354, + 'pinned' => false, + 'link' => 'http://example.com/', + 'faviconLink' => 'http://example.com/favicon.png', + 'folderId' => 0, + 'unreadCount' => 50048, + 'ordering' => 0, 'updateErrorCount' => 0, - 'lastUpdateError' => '', + 'lastUpdateError' => '', ], [ - 'id' => 42, - 'url' => 'http://example.org/news.atom', - 'title' => 'Second example feed', - 'added' => 1495287354, - 'pinned' => true, - 'link' => 'http://example.org/', - 'faviconLink' => 'http://example.org/favicon.png', - 'folderId' => 8, - 'unreadCount' => 23, - 'ordering' => 2, + 'id' => 42, + 'url' => 'http://example.org/news.atom', + 'title' => 'Second example feed', + 'added' => 1495287354, + 'pinned' => true, + 'link' => 'http://example.org/', + 'faviconLink' => 'http://example.org/favicon.png', + 'folderId' => 8, + 'unreadCount' => 23, + 'ordering' => 2, 'updateErrorCount' => 0, - 'lastUpdateError' => '', + 'lastUpdateError' => '', ], [ - 'id' => 47, - 'url' => 'http://example.net/news.atom', - 'title' => 'Third example feed', - 'added' => 1495287354, - 'pinned' => false, - 'link' => 'http://example.net/', - 'faviconLink' => 'http://example.net/favicon.png', - 'folderId' => 0, - 'unreadCount' => 0, - 'ordering' => 1, + 'id' => 47, + 'url' => 'http://example.net/news.atom', + 'title' => 'Third example feed', + 'added' => 1495287354, + 'pinned' => false, + 'link' => 'http://example.net/', + 'faviconLink' => 'http://example.net/favicon.png', + 'folderId' => 0, + 'unreadCount' => 0, + 'ordering' => 1, 'updateErrorCount' => 0, - 'lastUpdateError' => '', + 'lastUpdateError' => '', ], ], ]; protected $articles = [ 'db' => [ [ - 'id' => 101, - 'url' => 'http://example.com/1', - 'title' => 'Article title 1', - 'author' => '', - 'content' => '

Article content 1

', - 'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda', + 'id' => 101, + 'url' => 'http://example.com/1', + 'title' => 'Article title 1', + 'author' => '', + 'content' => '

Article content 1

', + 'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda', 'published_date' => '2000-01-01 00:00:00', - 'edited_date' => '2000-01-01 00:00:01', - 'modified_date' => '2000-01-01 01:00:00', - 'unread' => 1, - 'starred' => 0, - 'edition' => 101, - 'subscription' => 8, - 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', - 'media_url' => null, - 'media_type' => null, + 'edited_date' => '2000-01-01 00:00:01', + 'modified_date' => '2000-01-01 01:00:00', + 'unread' => 1, + 'starred' => 0, + 'edition' => 101, + 'subscription' => 8, + 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', + 'media_url' => null, + 'media_type' => null, ], [ - 'id' => 102, - 'url' => 'http://example.com/2', - 'title' => 'Article title 2', - 'author' => '', - 'content' => '

Article content 2

', - 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', + 'id' => 102, + 'url' => 'http://example.com/2', + 'title' => 'Article title 2', + 'author' => '', + 'content' => '

Article content 2

', + 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', 'published_date' => '2000-01-02 00:00:00', - 'edited_date' => '2000-01-02 00:00:02', - 'modified_date' => '2000-01-02 02:00:00', - 'unread' => 0, - 'starred' => 0, - 'edition' => 202, - 'subscription' => 8, - 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', - 'media_url' => "http://example.com/text", - 'media_type' => "text/plain", + 'edited_date' => '2000-01-02 00:00:02', + 'modified_date' => '2000-01-02 02:00:00', + 'unread' => 0, + 'starred' => 0, + 'edition' => 202, + 'subscription' => 8, + 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', + 'media_url' => "http://example.com/text", + 'media_type' => "text/plain", ], [ - 'id' => 103, - 'url' => 'http://example.com/3', - 'title' => 'Article title 3', - 'author' => '', - 'content' => '

Article content 3

', - 'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92', + 'id' => 103, + 'url' => 'http://example.com/3', + 'title' => 'Article title 3', + 'author' => '', + 'content' => '

Article content 3

', + 'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92', 'published_date' => '2000-01-03 00:00:00', - 'edited_date' => '2000-01-03 00:00:03', - 'modified_date' => '2000-01-03 03:00:00', - 'unread' => 1, - 'starred' => 1, - 'edition' => 203, - 'subscription' => 9, - 'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b', - 'media_url' => "http://example.com/video", - 'media_type' => "video/webm", + 'edited_date' => '2000-01-03 00:00:03', + 'modified_date' => '2000-01-03 03:00:00', + 'unread' => 1, + 'starred' => 1, + 'edition' => 203, + 'subscription' => 9, + 'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b', + 'media_url' => "http://example.com/video", + 'media_type' => "video/webm", ], [ - 'id' => 104, - 'url' => 'http://example.com/4', - 'title' => 'Article title 4', - 'author' => '', - 'content' => '

Article content 4

', - 'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180', + 'id' => 104, + 'url' => 'http://example.com/4', + 'title' => 'Article title 4', + 'author' => '', + 'content' => '

Article content 4

', + 'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180', 'published_date' => '2000-01-04 00:00:00', - 'edited_date' => '2000-01-04 00:00:04', - 'modified_date' => '2000-01-04 04:00:00', - 'unread' => 0, - 'starred' => 1, - 'edition' => 204, - 'subscription' => 9, - 'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9', - 'media_url' => "http://example.com/image", - 'media_type' => "image/svg+xml", + 'edited_date' => '2000-01-04 00:00:04', + 'modified_date' => '2000-01-04 04:00:00', + 'unread' => 0, + 'starred' => 1, + 'edition' => 204, + 'subscription' => 9, + 'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9', + 'media_url' => "http://example.com/image", + 'media_type' => "image/svg+xml", ], [ - 'id' => 105, - 'url' => 'http://example.com/5', - 'title' => 'Article title 5', - 'author' => '', - 'content' => '

Article content 5

', - 'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41', + 'id' => 105, + 'url' => 'http://example.com/5', + 'title' => 'Article title 5', + 'author' => '', + 'content' => '

Article content 5

', + 'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41', 'published_date' => '2000-01-05 00:00:00', - 'edited_date' => '2000-01-05 00:00:05', - 'modified_date' => '2000-01-05 05:00:00', - 'unread' => 1, - 'starred' => 0, - 'edition' => 305, - 'subscription' => 10, - 'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba', - 'media_url' => "http://example.com/audio", - 'media_type' => "audio/ogg", + 'edited_date' => '2000-01-05 00:00:05', + 'modified_date' => '2000-01-05 05:00:00', + 'unread' => 1, + 'starred' => 0, + 'edition' => 305, + 'subscription' => 10, + 'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba', + 'media_url' => "http://example.com/audio", + 'media_type' => "audio/ogg", ], ], 'rest' => [ [ - 'id' => 101, - 'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda', - 'guidHash' => "101", - 'url' => 'http://example.com/1', - 'title' => 'Article title 1', - 'author' => '', - 'pubDate' => 946684801, - 'body' => '

Article content 1

', + 'id' => 101, + 'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda', + 'guidHash' => "101", + 'url' => 'http://example.com/1', + 'title' => 'Article title 1', + 'author' => '', + 'pubDate' => 946684801, + 'body' => '

Article content 1

', 'enclosureMime' => "", 'enclosureLink' => "", - 'feedId' => 8, - 'unread' => true, - 'starred' => false, - 'lastModified' => 946688400, - 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', + 'feedId' => 8, + 'unread' => true, + 'starred' => false, + 'lastModified' => 946688400, + 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', ], [ - 'id' => 202, - 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', - 'guidHash' => "102", - 'url' => 'http://example.com/2', - 'title' => 'Article title 2', - 'author' => '', - 'pubDate' => 946771202, - 'body' => '

Article content 2

', + 'id' => 202, + 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', + 'guidHash' => "102", + 'url' => 'http://example.com/2', + 'title' => 'Article title 2', + 'author' => '', + 'pubDate' => 946771202, + 'body' => '

Article content 2

', 'enclosureMime' => "text/plain", 'enclosureLink' => "http://example.com/text", - 'feedId' => 8, - 'unread' => false, - 'starred' => false, - 'lastModified' => 946778400, - 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', + 'feedId' => 8, + 'unread' => false, + 'starred' => false, + 'lastModified' => 946778400, + 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', ], [ - 'id' => 203, - 'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92', - 'guidHash' => "103", - 'url' => 'http://example.com/3', - 'title' => 'Article title 3', - 'author' => '', - 'pubDate' => 946857603, - 'body' => '

Article content 3

', + 'id' => 203, + 'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92', + 'guidHash' => "103", + 'url' => 'http://example.com/3', + 'title' => 'Article title 3', + 'author' => '', + 'pubDate' => 946857603, + 'body' => '

Article content 3

', 'enclosureMime' => "video/webm", 'enclosureLink' => "http://example.com/video", - 'feedId' => 9, - 'unread' => true, - 'starred' => true, - 'lastModified' => 946868400, - 'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b', + 'feedId' => 9, + 'unread' => true, + 'starred' => true, + 'lastModified' => 946868400, + 'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b', ], [ - 'id' => 204, - 'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180', - 'guidHash' => "104", - 'url' => 'http://example.com/4', - 'title' => 'Article title 4', - 'author' => '', - 'pubDate' => 946944004, - 'body' => '

Article content 4

', + 'id' => 204, + 'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180', + 'guidHash' => "104", + 'url' => 'http://example.com/4', + 'title' => 'Article title 4', + 'author' => '', + 'pubDate' => 946944004, + 'body' => '

Article content 4

', 'enclosureMime' => "image/svg+xml", 'enclosureLink' => "http://example.com/image", - 'feedId' => 9, - 'unread' => false, - 'starred' => true, - 'lastModified' => 946958400, - 'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9', + 'feedId' => 9, + 'unread' => false, + 'starred' => true, + 'lastModified' => 946958400, + 'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9', ], [ - 'id' => 305, - 'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41', - 'guidHash' => "105", - 'url' => 'http://example.com/5', - 'title' => 'Article title 5', - 'author' => '', - 'pubDate' => 947030405, - 'body' => '

Article content 5

', + 'id' => 305, + 'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41', + 'guidHash' => "105", + 'url' => 'http://example.com/5', + 'title' => 'Article title 5', + 'author' => '', + 'pubDate' => 947030405, + 'body' => '

Article content 5

', 'enclosureMime' => "audio/ogg", 'enclosureLink' => "http://example.com/audio", - 'feedId' => 10, - 'unread' => true, - 'starred' => false, - 'lastModified' => 947048400, - 'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba', + 'feedId' => 10, + 'unread' => true, + 'starred' => false, + 'lastModified' => 947048400, + 'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba', ], ], ]; @@ -430,10 +430,10 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { public function provideFolderCreations(): array { return [ - [['name' => "Software"], true, 1, new Response(['folders' => [['id'=> 1, 'name' => "Software"]]])], - [['name' => "Software"], false, 1, new Response(['folders' => [['id'=> 1, 'name' => "Software"]]])], - [['name' => "Hardware"], true, "2", new Response(['folders' => [['id'=> 2, 'name' => "Hardware"]]])], - [['name' => "Hardware"], false, "2", new Response(['folders' => [['id'=> 2, 'name' => "Hardware"]]])], + [['name' => "Software"], true, 1, new Response(['folders' => [['id' => 1, 'name' => "Software"]]])], + [['name' => "Software"], false, 1, new Response(['folders' => [['id' => 1, 'name' => "Software"]]])], + [['name' => "Hardware"], true, "2", new Response(['folders' => [['id' => 2, 'name' => "Hardware"]]])], + [['name' => "Hardware"], false, "2", new Response(['folders' => [['id' => 2, 'name' => "Hardware"]]])], [['name' => "Software"], true, new ExceptionInput("constraintViolation"), new EmptyResponse(409)], [['name' => ""], true, new ExceptionInput("whitespace"), new EmptyResponse(422)], [['name' => " "], true, new ExceptionInput("whitespace"), new EmptyResponse(422)], @@ -476,7 +476,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { public function testRetrieveServerVersion(): void { $exp = new Response([ - 'version' => V1_2::VERSION, + 'version' => V1_2::VERSION, 'arsse_version' => Arsse::VERSION, ]); $this->assertMessage($exp, $this->req("GET", "/version")); @@ -484,7 +484,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { public function testListSubscriptions(): void { $exp1 = [ - 'feeds' => [], + 'feeds' => [], 'starredCount' => 0, ]; $exp2 = [ @@ -558,10 +558,10 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { public function testMoveASubscription(): void { $in = [ ['folderId' => 0], - ['folderId' => 42], + ['folderId' => 42], ['folderId' => 2112], - ['folderId' => 42], - ['folderId' => -1], + ['folderId' => 42], + ['folderId' => -1], [], ]; \Phake::when(Arsse::$db)->subscriptionPropertiesSet(Arsse::$user->id, 1, ['folder' => 42])->thenReturn(true); @@ -616,11 +616,11 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { public function testListStaleFeeds(): void { $out = [ [ - 'id' => 42, + 'id' => 42, 'userId' => "", ], [ - 'id' => 2112, + 'id' => 2112, 'userId' => "", ], ]; @@ -632,10 +632,10 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { public function testUpdateAFeed(): void { $in = [ ['feedId' => 42], // valid - ['feedId' => 2112], // feed does not exist + ['feedId' => 2112], // feed does not exist ['feedId' => "ook"], // invalid ID - ['feedId' => -1], // invalid ID - ['feed' => 42], // invalid input + ['feedId' => -1], // invalid ID + ['feed' => 42], // invalid input ]; \Phake::when(Arsse::$db)->feedUpdate(42)->thenReturn(true); \Phake::when(Arsse::$db)->feedUpdate(2112)->thenThrow(new ExceptionInput("subjectMissing")); @@ -654,17 +654,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { $t = new \DateTime; $in = [ ['type' => 0, 'id' => 42], // type=0 => subscription/feed - ['type' => 1, 'id' => 2112], // type=1 => folder - ['type' => 0, 'id' => -1], // type=0 => subscription/feed; invalid ID - ['type' => 1, 'id' => -1], // type=1 => folder; invalid ID - ['type' => 2, 'id' => 0], // type=2 => starred - ['type' => 3, 'id' => 0], // type=3 => all (default); base context - ['oldestFirst' => true, 'batchSize' => 10, 'offset' => 5], - ['oldestFirst' => false, 'batchSize' => 5, 'offset' => 5], - ['getRead' => true], // base context - ['getRead' => false], + ['type' => 1, 'id' => 2112], // type=1 => folder + ['type' => 0, 'id' => -1], // type=0 => subscription/feed; invalid ID + ['type' => 1, 'id' => -1], // type=1 => folder; invalid ID + ['type' => 2, 'id' => 0], // type=2 => starred + ['type' => 3, 'id' => 0], // type=3 => all (default); base context + ['oldestFirst' => true, 'batchSize' => 10, 'offset' => 5], + ['oldestFirst' => false, 'batchSize' => 5, 'offset' => 5], + ['getRead' => true], // base context + ['getRead' => false], ['lastModified' => $t->getTimestamp()], - ['oldestFirst' => false, 'batchSize' => 5, 'offset' => 0], // offset=0 should not set the latestEdition context + ['oldestFirst' => false, 'batchSize' => 5, 'offset' => 0], // offset=0 should not set the latestEdition context ]; \Phake::when(Arsse::$db)->articleList->thenReturn(new Result($this->v($this->articles['db']))); \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->subscription(42), $this->anything(), ["edition desc"])->thenThrow(new ExceptionInput("idMissing")); @@ -834,12 +834,12 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { \Phake::when(Arsse::$db)->metaGet("service_last_checkin")->thenReturn(Date::transform($valid, "sql"))->thenReturn(Date::transform($invalid, "sql")); \Phake::when(Arsse::$db)->driverCharsetAcceptable->thenReturn(true)->thenReturn(false); $arr1 = $arr2 = [ - 'version' => V1_2::VERSION, + 'version' => V1_2::VERSION, 'arsse_version' => Arsse::VERSION, - 'warnings' => [ + 'warnings' => [ 'improperlyConfiguredCron' => false, - 'incorrectDbCharset' => false, - ] + 'incorrectDbCharset' => false, + ], ]; $arr2['warnings']['improperlyConfiguredCron'] = true; $arr2['warnings']['incorrectDbCharset'] = true; @@ -864,14 +864,14 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { public function testQueryTheUserStatus(): void { $act = $this->req("GET", "/user"); $exp = new Response([ - 'userId' => Arsse::$user->id, - 'displayName' => Arsse::$user->id, + 'userId' => Arsse::$user->id, + 'displayName' => Arsse::$user->id, 'lastLoginTimestamp' => $this->approximateTime($act->getPayload()['lastLoginTimestamp'], new \DateTimeImmutable), - 'avatar' => null, + 'avatar' => null, ]); $this->assertMessage($exp, $act); } - + public function testPreferJsonOverQueryParameters(): void { $in = ['name' => "Software"]; $url = "/folders?name=Hardware"; @@ -884,7 +884,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { $exp = new Response(['folders' => [$out1]]); $this->assertMessage($exp, $this->req("POST", "/folders?name=Hardware", json_encode($in))); } - + public function testMeldJsonAndQueryParameters(): void { $in = ['oldestFirst' => true]; $url = "/items?type=2"; diff --git a/tests/cases/REST/NextcloudNews/TestVersions.php b/tests/cases/REST/NextcloudNews/TestVersions.php index ba0ae3a..aadb88d 100644 --- a/tests/cases/REST/NextcloudNews/TestVersions.php +++ b/tests/cases/REST/NextcloudNews/TestVersions.php @@ -8,7 +8,6 @@ namespace JKingWeb\Arsse\TestCase\REST\NextcloudNews; use JKingWeb\Arsse\REST\NextcloudNews\Versions; use Psr\Http\Message\ResponseInterface; -use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\Response\JsonResponse as Response; use Laminas\Diactoros\Response\EmptyResponse; diff --git a/tests/cases/REST/TestREST.php b/tests/cases/REST/TestREST.php index 3983fd2..da45893 100644 --- a/tests/cases/REST/TestREST.php +++ b/tests/cases/REST/TestREST.php @@ -199,53 +199,53 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { public function provideCorsHeaders(): iterable { return [ ["GET", ['Origin' => "null"], [], [ - 'Access-Control-Allow-Origin' => "null", + 'Access-Control-Allow-Origin' => "null", 'Access-Control-Allow-Credentials' => "true", - 'Vary' => "Origin", + 'Vary' => "Origin", ]], ["GET", ['Origin' => "http://example"], [], [ - 'Access-Control-Allow-Origin' => "http://example", + 'Access-Control-Allow-Origin' => "http://example", 'Access-Control-Allow-Credentials' => "true", - 'Vary' => "Origin", + 'Vary' => "Origin", ]], ["GET", ['Origin' => "http://example"], ['Content-Type' => "text/plain; charset=utf-8"], [ - 'Access-Control-Allow-Origin' => "http://example", + 'Access-Control-Allow-Origin' => "http://example", 'Access-Control-Allow-Credentials' => "true", - 'Vary' => "Origin", - 'Content-Type' => "text/plain; charset=utf-8", + 'Vary' => "Origin", + 'Content-Type' => "text/plain; charset=utf-8", ]], ["GET", ['Origin' => "http://example"], ['Vary' => "Content-Type"], [ - 'Access-Control-Allow-Origin' => "http://example", + 'Access-Control-Allow-Origin' => "http://example", 'Access-Control-Allow-Credentials' => "true", - 'Vary' => ["Content-Type", "Origin"], + 'Vary' => ["Content-Type", "Origin"], ]], ["OPTIONS", ['Origin' => "http://example"], [], [ - 'Access-Control-Allow-Origin' => "http://example", + 'Access-Control-Allow-Origin' => "http://example", 'Access-Control-Allow-Credentials' => "true", - 'Access-Control-Max-Age' => (string) (60 *60 *24), - 'Vary' => "Origin", + 'Access-Control-Max-Age' => (string) (60 * 60 * 24), + 'Vary' => "Origin", ]], ["OPTIONS", ['Origin' => "http://example"], ['Allow' => "GET, PUT, HEAD, OPTIONS"], [ - 'Allow' => "GET, PUT, HEAD, OPTIONS", - 'Access-Control-Allow-Origin' => "http://example", + 'Allow' => "GET, PUT, HEAD, OPTIONS", + 'Access-Control-Allow-Origin' => "http://example", 'Access-Control-Allow-Credentials' => "true", - 'Access-Control-Allow-Methods' => "GET, PUT, HEAD, OPTIONS", - 'Access-Control-Max-Age' => (string) (60 *60 *24), - 'Vary' => "Origin", + 'Access-Control-Allow-Methods' => "GET, PUT, HEAD, OPTIONS", + 'Access-Control-Max-Age' => (string) (60 * 60 * 24), + 'Vary' => "Origin", ]], ["OPTIONS", ['Origin' => "http://example", 'Access-Control-Request-Headers' => "Content-Type, If-None-Match"], [], [ - 'Access-Control-Allow-Origin' => "http://example", + 'Access-Control-Allow-Origin' => "http://example", 'Access-Control-Allow-Credentials' => "true", - 'Access-Control-Allow-Headers' => "Content-Type, If-None-Match", - 'Access-Control-Max-Age' => (string) (60 *60 *24), - 'Vary' => "Origin", + 'Access-Control-Allow-Headers' => "Content-Type, If-None-Match", + 'Access-Control-Max-Age' => (string) (60 * 60 * 24), + 'Vary' => "Origin", ]], ["OPTIONS", ['Origin' => "http://example", 'Access-Control-Request-Headers' => ["Content-Type", "If-None-Match"]], [], [ - 'Access-Control-Allow-Origin' => "http://example", + 'Access-Control-Allow-Origin' => "http://example", 'Access-Control-Allow-Credentials' => "true", - 'Access-Control-Allow-Headers' => "Content-Type,If-None-Match", - 'Access-Control-Max-Age' => (string) (60 *60 *24), - 'Vary' => "Origin", + 'Access-Control-Allow-Headers' => "Content-Type,If-None-Match", + 'Access-Control-Max-Age' => (string) (60 * 60 * 24), + 'Vary' => "Origin", ]], ]; } @@ -295,7 +295,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { } /** @dataProvider provideMockRequests */ - public function testDispatchRequests(ServerRequest $req, string $method, bool $called, string $class = "", string $target =""): void { + public function testDispatchRequests(ServerRequest $req, string $method, bool $called, string $class = "", string $target = ""): void { $r = \Phake::partialMock(REST::class); \Phake::when($r)->normalizeResponse->thenReturnCallback(function($res) { return $res; diff --git a/tests/cases/REST/TinyTinyRSS/TestAPI.php b/tests/cases/REST/TinyTinyRSS/TestAPI.php index 0db7f1f..cfd671a 100644 --- a/tests/cases/REST/TinyTinyRSS/TestAPI.php +++ b/tests/cases/REST/TinyTinyRSS/TestAPI.php @@ -17,7 +17,6 @@ use JKingWeb\Arsse\Db\ExceptionInput; use JKingWeb\Arsse\Db\Transaction; use JKingWeb\Arsse\REST\TinyTinyRSS\API; use Psr\Http\Message\ResponseInterface; -use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\Response\JsonResponse as Response; use Laminas\Diactoros\Response\EmptyResponse; @@ -58,44 +57,44 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { protected $starred = ['total' => 10, 'unread' => 4, 'read' => 6]; protected $articles = [ [ - 'id' => 101, - 'url' => 'http://example.com/1', - 'title' => 'Article title 1', + 'id' => 101, + 'url' => 'http://example.com/1', + 'title' => 'Article title 1', 'subscription_title' => "Feed 11", - 'author' => '', - 'content' => '

Article content 1

', - 'guid' => '', - 'published_date' => '2000-01-01 00:00:00', - 'edited_date' => '2000-01-01 00:00:01', - 'modified_date' => '2000-01-01 01:00:00', - 'unread' => 1, - 'starred' => 0, - 'edition' => 101, - 'subscription' => 8, - 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', - 'media_url' => null, - 'media_type' => null, - 'note' => "", + 'author' => '', + 'content' => '

Article content 1

', + 'guid' => '', + 'published_date' => '2000-01-01 00:00:00', + 'edited_date' => '2000-01-01 00:00:01', + 'modified_date' => '2000-01-01 01:00:00', + 'unread' => 1, + 'starred' => 0, + 'edition' => 101, + 'subscription' => 8, + 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', + 'media_url' => null, + 'media_type' => null, + 'note' => "", ], [ - 'id' => 102, - 'url' => 'http://example.com/2', - 'title' => 'Article title 2', + 'id' => 102, + 'url' => 'http://example.com/2', + 'title' => 'Article title 2', 'subscription_title' => "Feed 11", - 'author' => 'J. King', - 'content' => '

Article content 2

', - 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', - 'published_date' => '2000-01-02 00:00:00', - 'edited_date' => '2000-01-02 00:00:02', - 'modified_date' => '2000-01-02 02:00:00', - 'unread' => 0, - 'starred' => 0, - 'edition' => 202, - 'subscription' => 8, - 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', - 'media_url' => "http://example.com/text", - 'media_type' => "text/plain", - 'note' => "Note 2", + 'author' => 'J. King', + 'content' => '

Article content 2

', + 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', + 'published_date' => '2000-01-02 00:00:00', + 'edited_date' => '2000-01-02 00:00:02', + 'modified_date' => '2000-01-02 02:00:00', + 'unread' => 0, + 'starred' => 0, + 'edition' => 202, + 'subscription' => 8, + 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', + 'media_url' => "http://example.com/text", + 'media_type' => "text/plain", + 'note' => "Note 2", ], ]; // text from https://corrigeur.fr/lorem-ipsum-traduction-origine.php @@ -140,8 +139,8 @@ LONG_STRING; protected function respGood($content = null, $seq = 0): Response { return new Response([ - 'seq' => $seq, - 'status' => 0, + 'seq' => $seq, + 'status' => 0, 'content' => $content, ]); } @@ -149,8 +148,8 @@ LONG_STRING; protected function respErr(string $msg, $content = [], $seq = 0): Response { $err = ['error' => $msg]; return new Response([ - 'seq' => $seq, - 'status' => 1, + 'seq' => $seq, + 'status' => 1, 'content' => array_merge($err, $content, $err), ]); } @@ -167,7 +166,7 @@ LONG_STRING; \Phake::when(Arsse::$db)->begin->thenReturn(\Phake::mock(Transaction::class)); \Phake::when(Arsse::$db)->sessionResume->thenThrow(new \JKingWeb\Arsse\User\ExceptionSession("invalid")); \Phake::when(Arsse::$db)->sessionResume("PriestsOfSyrinx")->thenReturn([ - 'id' => "PriestsOfSyrinx", + 'id' => "PriestsOfSyrinx", 'created' => "2000-01-01 00:00:00", 'expires' => "2112-12-21 21:12:00", 'user' => Arsse::$user->id, @@ -241,13 +240,13 @@ LONG_STRING; Arsse::$user->id = null; self::setConf($conf); \Phake::when(Arsse::$db)->sessionResume("PriestsOfSyrinx")->thenReturn([ - 'id' => "PriestsOfSyrinx", + 'id' => "PriestsOfSyrinx", 'created' => "2000-01-01 00:00:00", 'expires' => "2112-12-21 21:12:00", 'user' => "john.doe@example.com", ]); \Phake::when(Arsse::$db)->sessionResume("ClockworkAngels")->thenReturn([ - 'id' => "ClockworkAngels", + 'id' => "ClockworkAngels", 'created' => "2000-01-01 00:00:00", 'expires' => "2112-12-21 21:12:00", 'user' => "jane.doe@example.com", @@ -277,21 +276,21 @@ LONG_STRING; public function generateLoginRequests(string $type): array { $john = "john.doe@example.com"; $johnGood = [ - 'user' => $john, + 'user' => $john, 'password' => "secret", ]; $johnBad = [ - 'user' => $john, + 'user' => $john, 'password' => "superman", ]; $johnSess = ["PriestsOfSyrinx", "SolarFederation"]; $jane = "jane.doe@example.com"; $janeGood = [ - 'user' => $jane, + 'user' => $jane, 'password' => "superman", ]; $janeBad = [ - 'user' => $jane, + 'user' => $jane, 'password' => "secret", ]; $janeSess = ["ClockworkAngels", "SevenCitiesOfGold"]; @@ -305,29 +304,29 @@ LONG_STRING; $sidJane = "ClockworkAngels"; $sidBad = "TheWatchmaker"; $defaults = [ - 'userPreAuth' => false, + 'userPreAuth' => false, 'userHTTPAuthRequired' => false, - 'userSessionEnforced' => true, + 'userSessionEnforced' => true, ]; $preAuth = [ - 'userPreAuth' => true, + 'userPreAuth' => true, 'userHTTPAuthRequired' => false, // implied true by pre-auth - 'userSessionEnforced' => true, + 'userSessionEnforced' => true, ]; $httpReq = [ - 'userPreAuth' => false, + 'userPreAuth' => false, 'userHTTPAuthRequired' => true, - 'userSessionEnforced' => true, + 'userSessionEnforced' => true, ]; $noSess = [ - 'userPreAuth' => false, + 'userPreAuth' => false, 'userHTTPAuthRequired' => false, - 'userSessionEnforced' => false, + 'userSessionEnforced' => false, ]; $fullHttp = [ - 'userPreAuth' => false, + 'userPreAuth' => false, 'userHTTPAuthRequired' => true, - 'userSessionEnforced' => false, + 'userSessionEnforced' => false, ]; $http401 = new EmptyResponse(401); if ($type === "login") { @@ -573,7 +572,7 @@ LONG_STRING; 'sid' => "PriestsOfSyrinx", ]; $exp = $this->respGood([ - 'version' => \JKingWeb\Arsse\REST\TinyTinyRSS\API::VERSION, + 'version' => \JKingWeb\Arsse\REST\TinyTinyRSS\API::VERSION, 'arsse_version' => Arsse::VERSION, ]); $this->assertMessage($exp, $this->req($data)); @@ -984,7 +983,7 @@ LONG_STRING; public function testAddALabel(): void { $in = [ ['op' => "addLabel", 'sid' => "PriestsOfSyrinx", 'caption' => "Software"], - ['op' => "addLabel", 'sid' => "PriestsOfSyrinx", 'caption' => "Hardware",], + ['op' => "addLabel", 'sid' => "PriestsOfSyrinx", 'caption' => "Hardware"], ['op' => "addLabel", 'sid' => "PriestsOfSyrinx"], ['op' => "addLabel", 'sid' => "PriestsOfSyrinx", 'caption' => ""], ['op' => "addLabel", 'sid' => "PriestsOfSyrinx", 'caption' => " "], @@ -1301,9 +1300,9 @@ LONG_STRING; \Phake::when(Arsse::$db)->articleCount($this->anything(), $this->equalTo((new Context)->unread(true)->modifiedSince(Date::sub("PT24H")), 2))->thenReturn(7); \Phake::when(Arsse::$db)->articleStarred($this->anything())->thenReturn($this->v($this->starred)); // the expectations are packed tightly since they're very verbose; one can use var_export() (or convert to JSON) to pretty-print them - $exp = ['categories'=>['identifier'=>'id','label'=>'name','items'=>[['name'=>'Special','id'=>'CAT:-1','bare_id'=>-1,'type'=>'category','unread'=>0,'items'=>[['name'=>'All articles','id'=>'FEED:-4','bare_id'=>-4,'icon'=>'images/folder.png','unread'=>35,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Fresh articles','id'=>'FEED:-3','bare_id'=>-3,'icon'=>'images/fresh.png','unread'=>7,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Starred articles','id'=>'FEED:-1','bare_id'=>-1,'icon'=>'images/star.png','unread'=>4,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Published articles','id'=>'FEED:-2','bare_id'=>-2,'icon'=>'images/feed.png','unread'=>0,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Archived articles','id'=>'FEED:0','bare_id'=>0,'icon'=>'images/archive.png','unread'=>0,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Recently read','id'=>'FEED:-6','bare_id'=>-6,'icon'=>'images/time.png','unread'=>0,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],],],['name'=>'Labels','id'=>'CAT:-2','bare_id'=>-2,'type'=>'category','unread'=>6,'items'=>[['name'=>'Fascinating','id'=>'FEED:-1027','bare_id'=>-1027,'unread'=>0,'icon'=>'images/label.png','type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'','fg_color'=>'','bg_color'=>'',],['name'=>'Interesting','id'=>'FEED:-1029','bare_id'=>-1029,'unread'=>0,'icon'=>'images/label.png','type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'','fg_color'=>'','bg_color'=>'',],['name'=>'Logical','id'=>'FEED:-1025','bare_id'=>-1025,'unread'=>0,'icon'=>'images/label.png','type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'','fg_color'=>'','bg_color'=>'',],],],['name'=>'Photography','id'=>'CAT:4','bare_id'=>4,'parent_id'=>null,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(0 feeds)','items'=>[],],['name'=>'Politics','id'=>'CAT:3','bare_id'=>3,'parent_id'=>null,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(3 feeds)','items'=>[['name'=>'Local','id'=>'CAT:5','bare_id'=>5,'parent_id'=>3,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(1 feed)','items'=>[['name'=>'Toronto Star','id'=>'FEED:2','bare_id'=>2,'icon'=>'feed-icons/2.ico','error'=>'oops','param'=>'2011-11-11T11:11:11Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],['name'=>'National','id'=>'CAT:6','bare_id'=>6,'parent_id'=>3,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(2 feeds)','items'=>[['name'=>'CBC News','id'=>'FEED:4','bare_id'=>4,'icon'=>'feed-icons/4.ico','error'=>'','param'=>'2017-10-09T15:58:34Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],['name'=>'Ottawa Citizen','id'=>'FEED:5','bare_id'=>5,'icon'=>false,'error'=>'','param'=>'2017-07-07T17:07:17Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],],],['name'=>'Science','id'=>'CAT:1','bare_id'=>1,'parent_id'=>null,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(2 feeds)','items'=>[['name'=>'Rocketry','id'=>'CAT:2','bare_id'=>2,'parent_id'=>1,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(1 feed)','items'=>[['name'=>'NASA JPL','id'=>'FEED:1','bare_id'=>1,'icon'=>false,'error'=>'','param'=>'2017-09-15T22:54:16Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],['name'=>'Ars Technica','id'=>'FEED:3','bare_id'=>3,'icon'=>'feed-icons/3.ico','error'=>'argh','param'=>'2016-05-23T06:40:02Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],['name'=>'Uncategorized','id'=>'CAT:0','bare_id'=>0,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'parent_id'=>null,'param'=>'(1 feed)','items'=>[['name'=>'Eurogamer','id'=>'FEED:6','bare_id'=>6,'icon'=>'feed-icons/6.ico','error'=>'','param'=>'2010-02-12T20:08:47Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],],],]; + $exp = ['categories' => ['identifier' => 'id','label' => 'name','items' => [['name' => 'Special','id' => 'CAT:-1','bare_id' => -1,'type' => 'category','unread' => 0,'items' => [['name' => 'All articles','id' => 'FEED:-4','bare_id' => -4,'icon' => 'images/folder.png','unread' => 35,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Fresh articles','id' => 'FEED:-3','bare_id' => -3,'icon' => 'images/fresh.png','unread' => 7,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Starred articles','id' => 'FEED:-1','bare_id' => -1,'icon' => 'images/star.png','unread' => 4,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Published articles','id' => 'FEED:-2','bare_id' => -2,'icon' => 'images/feed.png','unread' => 0,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Archived articles','id' => 'FEED:0','bare_id' => 0,'icon' => 'images/archive.png','unread' => 0,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Recently read','id' => 'FEED:-6','bare_id' => -6,'icon' => 'images/time.png','unread' => 0,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => '']]],['name' => 'Labels','id' => 'CAT:-2','bare_id' => -2,'type' => 'category','unread' => 6,'items' => [['name' => 'Fascinating','id' => 'FEED:-1027','bare_id' => -1027,'unread' => 0,'icon' => 'images/label.png','type' => 'feed','auxcounter' => 0,'error' => '','updated' => '','fg_color' => '','bg_color' => ''],['name' => 'Interesting','id' => 'FEED:-1029','bare_id' => -1029,'unread' => 0,'icon' => 'images/label.png','type' => 'feed','auxcounter' => 0,'error' => '','updated' => '','fg_color' => '','bg_color' => ''],['name' => 'Logical','id' => 'FEED:-1025','bare_id' => -1025,'unread' => 0,'icon' => 'images/label.png','type' => 'feed','auxcounter' => 0,'error' => '','updated' => '','fg_color' => '','bg_color' => '']]],['name' => 'Photography','id' => 'CAT:4','bare_id' => 4,'parent_id' => null,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(0 feeds)','items' => []],['name' => 'Politics','id' => 'CAT:3','bare_id' => 3,'parent_id' => null,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(3 feeds)','items' => [['name' => 'Local','id' => 'CAT:5','bare_id' => 5,'parent_id' => 3,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(1 feed)','items' => [['name' => 'Toronto Star','id' => 'FEED:2','bare_id' => 2,'icon' => 'feed-icons/2.ico','error' => 'oops','param' => '2011-11-11T11:11:11Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]],['name' => 'National','id' => 'CAT:6','bare_id' => 6,'parent_id' => 3,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(2 feeds)','items' => [['name' => 'CBC News','id' => 'FEED:4','bare_id' => 4,'icon' => 'feed-icons/4.ico','error' => '','param' => '2017-10-09T15:58:34Z','unread' => 0,'auxcounter' => 0,'checkbox' => false],['name' => 'Ottawa Citizen','id' => 'FEED:5','bare_id' => 5,'icon' => false,'error' => '','param' => '2017-07-07T17:07:17Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]]]],['name' => 'Science','id' => 'CAT:1','bare_id' => 1,'parent_id' => null,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(2 feeds)','items' => [['name' => 'Rocketry','id' => 'CAT:2','bare_id' => 2,'parent_id' => 1,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(1 feed)','items' => [['name' => 'NASA JPL','id' => 'FEED:1','bare_id' => 1,'icon' => false,'error' => '','param' => '2017-09-15T22:54:16Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]],['name' => 'Ars Technica','id' => 'FEED:3','bare_id' => 3,'icon' => 'feed-icons/3.ico','error' => 'argh','param' => '2016-05-23T06:40:02Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]],['name' => 'Uncategorized','id' => 'CAT:0','bare_id' => 0,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'parent_id' => null,'param' => '(1 feed)','items' => [['name' => 'Eurogamer','id' => 'FEED:6','bare_id' => 6,'icon' => 'feed-icons/6.ico','error' => '','param' => '2010-02-12T20:08:47Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]]]]]; $this->assertMessage($this->respGood($exp), $this->req($in[0])); - $exp = ['categories'=>['identifier'=>'id','label'=>'name','items'=>[['name'=>'Special','id'=>'CAT:-1','bare_id'=>-1,'type'=>'category','unread'=>0,'items'=>[['name'=>'All articles','id'=>'FEED:-4','bare_id'=>-4,'icon'=>'images/folder.png','unread'=>35,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Fresh articles','id'=>'FEED:-3','bare_id'=>-3,'icon'=>'images/fresh.png','unread'=>7,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Starred articles','id'=>'FEED:-1','bare_id'=>-1,'icon'=>'images/star.png','unread'=>4,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Published articles','id'=>'FEED:-2','bare_id'=>-2,'icon'=>'images/feed.png','unread'=>0,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Archived articles','id'=>'FEED:0','bare_id'=>0,'icon'=>'images/archive.png','unread'=>0,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],['name'=>'Recently read','id'=>'FEED:-6','bare_id'=>-6,'icon'=>'images/time.png','unread'=>0,'type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'',],],],['name'=>'Labels','id'=>'CAT:-2','bare_id'=>-2,'type'=>'category','unread'=>6,'items'=>[['name'=>'Fascinating','id'=>'FEED:-1027','bare_id'=>-1027,'unread'=>0,'icon'=>'images/label.png','type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'','fg_color'=>'','bg_color'=>'',],['name'=>'Interesting','id'=>'FEED:-1029','bare_id'=>-1029,'unread'=>0,'icon'=>'images/label.png','type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'','fg_color'=>'','bg_color'=>'',],['name'=>'Logical','id'=>'FEED:-1025','bare_id'=>-1025,'unread'=>0,'icon'=>'images/label.png','type'=>'feed','auxcounter'=>0,'error'=>'','updated'=>'','fg_color'=>'','bg_color'=>'',],],],['name'=>'Politics','id'=>'CAT:3','bare_id'=>3,'parent_id'=>null,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(3 feeds)','items'=>[['name'=>'Local','id'=>'CAT:5','bare_id'=>5,'parent_id'=>3,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(1 feed)','items'=>[['name'=>'Toronto Star','id'=>'FEED:2','bare_id'=>2,'icon'=>'feed-icons/2.ico','error'=>'oops','param'=>'2011-11-11T11:11:11Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],['name'=>'National','id'=>'CAT:6','bare_id'=>6,'parent_id'=>3,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(2 feeds)','items'=>[['name'=>'CBC News','id'=>'FEED:4','bare_id'=>4,'icon'=>'feed-icons/4.ico','error'=>'','param'=>'2017-10-09T15:58:34Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],['name'=>'Ottawa Citizen','id'=>'FEED:5','bare_id'=>5,'icon'=>false,'error'=>'','param'=>'2017-07-07T17:07:17Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],],],['name'=>'Science','id'=>'CAT:1','bare_id'=>1,'parent_id'=>null,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(2 feeds)','items'=>[['name'=>'Rocketry','id'=>'CAT:2','bare_id'=>2,'parent_id'=>1,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'param'=>'(1 feed)','items'=>[['name'=>'NASA JPL','id'=>'FEED:1','bare_id'=>1,'icon'=>false,'error'=>'','param'=>'2017-09-15T22:54:16Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],['name'=>'Ars Technica','id'=>'FEED:3','bare_id'=>3,'icon'=>'feed-icons/3.ico','error'=>'argh','param'=>'2016-05-23T06:40:02Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],['name'=>'Uncategorized','id'=>'CAT:0','bare_id'=>0,'type'=>'category','auxcounter'=>0,'unread'=>0,'child_unread'=>0,'checkbox'=>false,'parent_id'=>null,'param'=>'(1 feed)','items'=>[['name'=>'Eurogamer','id'=>'FEED:6','bare_id'=>6,'icon'=>'feed-icons/6.ico','error'=>'','param'=>'2010-02-12T20:08:47Z','unread'=>0,'auxcounter'=>0,'checkbox'=>false,],],],],],]; + $exp = ['categories' => ['identifier' => 'id','label' => 'name','items' => [['name' => 'Special','id' => 'CAT:-1','bare_id' => -1,'type' => 'category','unread' => 0,'items' => [['name' => 'All articles','id' => 'FEED:-4','bare_id' => -4,'icon' => 'images/folder.png','unread' => 35,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Fresh articles','id' => 'FEED:-3','bare_id' => -3,'icon' => 'images/fresh.png','unread' => 7,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Starred articles','id' => 'FEED:-1','bare_id' => -1,'icon' => 'images/star.png','unread' => 4,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Published articles','id' => 'FEED:-2','bare_id' => -2,'icon' => 'images/feed.png','unread' => 0,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Archived articles','id' => 'FEED:0','bare_id' => 0,'icon' => 'images/archive.png','unread' => 0,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => ''],['name' => 'Recently read','id' => 'FEED:-6','bare_id' => -6,'icon' => 'images/time.png','unread' => 0,'type' => 'feed','auxcounter' => 0,'error' => '','updated' => '']]],['name' => 'Labels','id' => 'CAT:-2','bare_id' => -2,'type' => 'category','unread' => 6,'items' => [['name' => 'Fascinating','id' => 'FEED:-1027','bare_id' => -1027,'unread' => 0,'icon' => 'images/label.png','type' => 'feed','auxcounter' => 0,'error' => '','updated' => '','fg_color' => '','bg_color' => ''],['name' => 'Interesting','id' => 'FEED:-1029','bare_id' => -1029,'unread' => 0,'icon' => 'images/label.png','type' => 'feed','auxcounter' => 0,'error' => '','updated' => '','fg_color' => '','bg_color' => ''],['name' => 'Logical','id' => 'FEED:-1025','bare_id' => -1025,'unread' => 0,'icon' => 'images/label.png','type' => 'feed','auxcounter' => 0,'error' => '','updated' => '','fg_color' => '','bg_color' => '']]],['name' => 'Politics','id' => 'CAT:3','bare_id' => 3,'parent_id' => null,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(3 feeds)','items' => [['name' => 'Local','id' => 'CAT:5','bare_id' => 5,'parent_id' => 3,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(1 feed)','items' => [['name' => 'Toronto Star','id' => 'FEED:2','bare_id' => 2,'icon' => 'feed-icons/2.ico','error' => 'oops','param' => '2011-11-11T11:11:11Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]],['name' => 'National','id' => 'CAT:6','bare_id' => 6,'parent_id' => 3,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(2 feeds)','items' => [['name' => 'CBC News','id' => 'FEED:4','bare_id' => 4,'icon' => 'feed-icons/4.ico','error' => '','param' => '2017-10-09T15:58:34Z','unread' => 0,'auxcounter' => 0,'checkbox' => false],['name' => 'Ottawa Citizen','id' => 'FEED:5','bare_id' => 5,'icon' => false,'error' => '','param' => '2017-07-07T17:07:17Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]]]],['name' => 'Science','id' => 'CAT:1','bare_id' => 1,'parent_id' => null,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(2 feeds)','items' => [['name' => 'Rocketry','id' => 'CAT:2','bare_id' => 2,'parent_id' => 1,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'param' => '(1 feed)','items' => [['name' => 'NASA JPL','id' => 'FEED:1','bare_id' => 1,'icon' => false,'error' => '','param' => '2017-09-15T22:54:16Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]],['name' => 'Ars Technica','id' => 'FEED:3','bare_id' => 3,'icon' => 'feed-icons/3.ico','error' => 'argh','param' => '2016-05-23T06:40:02Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]],['name' => 'Uncategorized','id' => 'CAT:0','bare_id' => 0,'type' => 'category','auxcounter' => 0,'unread' => 0,'child_unread' => 0,'checkbox' => false,'parent_id' => null,'param' => '(1 feed)','items' => [['name' => 'Eurogamer','id' => 'FEED:6','bare_id' => 6,'icon' => 'feed-icons/6.ico','error' => '','param' => '2010-02-12T20:08:47Z','unread' => 0,'auxcounter' => 0,'checkbox' => false]]]]]]; $this->assertMessage($this->respGood($exp), $this->req($in[1])); } @@ -1413,7 +1412,7 @@ LONG_STRING; ['id' => -3, 'title' => "Fresh articles", 'unread' => "7", 'cat_id' => -1], ['id' => -4, 'title' => "All articles", 'unread' => "35", 'cat_id' => -1], ['id' => -6, 'title' => "Recently read", 'unread' => 0, 'cat_id' => -1], - ['id' => 0, 'title' => "Archived articles", 'unread' => "0", 'cat_id' => -1], + ['id' => 0, 'title' => "Archived articles", 'unread' => "0", 'cat_id' => -1], ], [ ['id' => -1, 'title' => "Starred articles", 'unread' => "4", 'cat_id' => -1], @@ -1450,7 +1449,7 @@ LONG_STRING; ['id' => -3, 'title' => "Fresh articles", 'unread' => "7", 'cat_id' => -1], ['id' => -4, 'title' => "All articles", 'unread' => "35", 'cat_id' => -1], ['id' => -6, 'title' => "Recently read", 'unread' => 0, 'cat_id' => -1], - ['id' => 0, 'title' => "Archived articles", 'unread' => "0", 'cat_id' => -1], + ['id' => 0, 'title' => "Archived articles", 'unread' => "0", 'cat_id' => -1], ['id' => 3, 'title' => 'Ars Technica', 'unread' => 2, 'cat_id' => 1, 'feed_url' => " http://example.com/3", 'has_icon' => true, 'last_updated' => 1463985602, 'order_id' => 1], ['id' => 4, 'title' => 'CBC News', 'unread' => 6, 'cat_id' => 6, 'feed_url' => " http://example.com/4", 'has_icon' => true, 'last_updated' => 1507564714, 'order_id' => 2], ['id' => 6, 'title' => 'Eurogamer', 'unread' => 0, 'cat_id' => 0, 'feed_url' => " http://example.com/6", 'has_icon' => true, 'last_updated' => 1266005327, 'order_id' => 3], @@ -1507,7 +1506,7 @@ LONG_STRING; }); } - protected function reduceFolders(int $id = null) : int { + protected function reduceFolders(int $id = null): int { $out = 0; foreach ($this->filterFolders($id) as $f) { $out += $this->reduceFolders($f['id']); @@ -1631,42 +1630,42 @@ LONG_STRING; $this->assertMessage($exp, $this->req($in[3])); $exp = [ [ - 'id' => "101", - 'guid' => null, - 'title' => 'Article title 1', - 'link' => 'http://example.com/1', - 'labels' => [], - 'unread' => true, - 'marked' => false, - 'published' => false, - 'comments' => "", - 'author' => '', - 'updated' => strtotime('2000-01-01T00:00:01Z'), - 'feed_id' => "8", - 'feed_title' => "Feed 11", + 'id' => "101", + 'guid' => null, + 'title' => 'Article title 1', + 'link' => 'http://example.com/1', + 'labels' => [], + 'unread' => true, + 'marked' => false, + 'published' => false, + 'comments' => "", + 'author' => '', + 'updated' => strtotime('2000-01-01T00:00:01Z'), + 'feed_id' => "8", + 'feed_title' => "Feed 11", 'attachments' => [], - 'score' => 0, - 'note' => null, - 'lang' => "", - 'content' => '

Article content 1

', + 'score' => 0, + 'note' => null, + 'lang' => "", + 'content' => '

Article content 1

', ], [ - 'id' => "102", - 'guid' => "SHA256:5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7", - 'title' => 'Article title 2', - 'link' => 'http://example.com/2', + 'id' => "102", + 'guid' => "SHA256:5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7", + 'title' => 'Article title 2', + 'link' => 'http://example.com/2', 'labels' => [ [-1025, "Logical", "", ""], [-1027, "Fascinating", "", ""], ], - 'unread' => false, - 'marked' => false, - 'published' => false, - 'comments' => "", - 'author' => "J. King", - 'updated' => strtotime('2000-01-02T00:00:02Z'), - 'feed_id' => "8", - 'feed_title' => "Feed 11", + 'unread' => false, + 'marked' => false, + 'published' => false, + 'comments' => "", + 'author' => "J. King", + 'updated' => strtotime('2000-01-02T00:00:02Z'), + 'feed_id' => "8", + 'feed_title' => "Feed 11", 'attachments' => [ [ 'id' => "0", @@ -1679,9 +1678,9 @@ LONG_STRING; 'post_id' => "102", ], ], - 'score' => 0, - 'note' => "Note 2", - 'lang' => "", + 'score' => 0, + 'note' => "Note 2", + 'lang' => "", 'content' => '

Article content 2

', ], ]; @@ -2012,44 +2011,44 @@ LONG_STRING; protected function generateHeadlines(int $id): Result { return new Result($this->v([ [ - 'id' => $id, - 'url' => 'http://example.com/1', - 'title' => 'Article title 1', + 'id' => $id, + 'url' => 'http://example.com/1', + 'title' => 'Article title 1', 'subscription_title' => "Feed 2112", - 'author' => '', - 'content' => '

“This & that, you know‽”

', - 'guid' => null, - 'published_date' => '2000-01-01 00:00:00', - 'edited_date' => '2000-01-01 00:00:00', - 'modified_date' => '2000-01-01 01:00:00', - 'unread' => 0, - 'starred' => 0, - 'edition' => 101, - 'subscription' => 12, - 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', - 'media_url' => null, - 'media_type' => null, - 'note' => "", + 'author' => '', + 'content' => '

“This & that, you know‽”

', + 'guid' => null, + 'published_date' => '2000-01-01 00:00:00', + 'edited_date' => '2000-01-01 00:00:00', + 'modified_date' => '2000-01-01 01:00:00', + 'unread' => 0, + 'starred' => 0, + 'edition' => 101, + 'subscription' => 12, + 'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207', + 'media_url' => null, + 'media_type' => null, + 'note' => "", ], [ - 'id' => 2112, - 'url' => 'http://example.com/2', - 'title' => 'Article title 2', + 'id' => 2112, + 'url' => 'http://example.com/2', + 'title' => 'Article title 2', 'subscription_title' => "Feed 11", - 'author' => 'J. King', - 'content' => $this->richContent, - 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', - 'published_date' => '2000-01-02 00:00:00', - 'edited_date' => '2000-01-02 00:00:02', - 'modified_date' => '2000-01-02 02:00:00', - 'unread' => 1, - 'starred' => 1, - 'edition' => 202, - 'subscription' => 8, - 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', - 'media_url' => "http://example.com/text", - 'media_type' => "text/plain", - 'note' => "Note 2", + 'author' => 'J. King', + 'content' => $this->richContent, + 'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7', + 'published_date' => '2000-01-02 00:00:00', + 'edited_date' => '2000-01-02 00:00:02', + 'modified_date' => '2000-01-02 02:00:00', + 'unread' => 1, + 'starred' => 1, + 'edition' => 202, + 'subscription' => 8, + 'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e', + 'media_url' => "http://example.com/text", + 'media_type' => "text/plain", + 'note' => "Note 2", ], ])); } @@ -2057,50 +2056,50 @@ LONG_STRING; protected function outputHeadlines(int $id): Response { return $this->respGood([ [ - 'id' => $id, - 'guid' => '', - 'title' => 'Article title 1', - 'link' => 'http://example.com/1', - 'labels' => [], - 'unread' => false, - 'marked' => false, - 'published' => false, - 'author' => '', - 'updated' => strtotime('2000-01-01T00:00:00Z'), - 'is_updated' => false, - 'feed_id' => "12", - 'feed_title' => "Feed 2112", - 'score' => 0, - 'note' => null, - 'lang' => "", - 'tags' => [], - 'comments_count' => 0, - 'comments_link' => "", + 'id' => $id, + 'guid' => '', + 'title' => 'Article title 1', + 'link' => 'http://example.com/1', + 'labels' => [], + 'unread' => false, + 'marked' => false, + 'published' => false, + 'author' => '', + 'updated' => strtotime('2000-01-01T00:00:00Z'), + 'is_updated' => false, + 'feed_id' => "12", + 'feed_title' => "Feed 2112", + 'score' => 0, + 'note' => null, + 'lang' => "", + 'tags' => [], + 'comments_count' => 0, + 'comments_link' => "", 'always_display_attachments' => false, ], [ - 'id' => 2112, - 'guid' => "SHA256:5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7", - 'title' => 'Article title 2', - 'link' => 'http://example.com/2', + 'id' => 2112, + 'guid' => "SHA256:5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7", + 'title' => 'Article title 2', + 'link' => 'http://example.com/2', 'labels' => [ [-1025, "Logical", "", ""], [-1027, "Fascinating", "", ""], ], - 'unread' => true, - 'marked' => true, - 'published' => false, - 'author' => "J. King", - 'updated' => strtotime('2000-01-02T00:00:02Z'), - 'is_updated' => true, - 'feed_id' => "8", - 'feed_title' => "Feed 11", - 'score' => 0, - 'note' => "Note 2", - 'lang' => "", - 'tags' => ["Boring", "Illogical"], - 'comments_count' => 0, - 'comments_link' => "", + 'unread' => true, + 'marked' => true, + 'published' => false, + 'author' => "J. King", + 'updated' => strtotime('2000-01-02T00:00:02Z'), + 'is_updated' => true, + 'feed_id' => "8", + 'feed_title' => "Feed 11", + 'score' => 0, + 'note' => "Note 2", + 'lang' => "", + 'tags' => ["Boring", "Illogical"], + 'comments_count' => 0, + 'comments_link' => "", 'always_display_attachments' => false, ], ]); diff --git a/tests/cases/REST/TinyTinyRSS/TestIcon.php b/tests/cases/REST/TinyTinyRSS/TestIcon.php index 3877ab7..38dbd8f 100644 --- a/tests/cases/REST/TinyTinyRSS/TestIcon.php +++ b/tests/cases/REST/TinyTinyRSS/TestIcon.php @@ -11,7 +11,6 @@ use JKingWeb\Arsse\User; use JKingWeb\Arsse\Database; use JKingWeb\Arsse\REST\TinyTinyRSS\Icon; use Psr\Http\Message\ResponseInterface; -use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\Response\EmptyResponse as Response; /** @covers \JKingWeb\Arsse\REST\TinyTinyRSS\Icon */ diff --git a/tests/cases/REST/TinyTinyRSS/TestSearch.php b/tests/cases/REST/TinyTinyRSS/TestSearch.php index f99ce7e..6999b0d 100644 --- a/tests/cases/REST/TinyTinyRSS/TestSearch.php +++ b/tests/cases/REST/TinyTinyRSS/TestSearch.php @@ -13,107 +13,107 @@ use JKingWeb\Arsse\REST\TinyTinyRSS\Search; class TestSearch extends \JKingWeb\Arsse\Test\AbstractTest { public function provideSearchStrings(): iterable { return [ - 'Blank string' => ["", new Context], - 'Whitespace only' => [" \n \t", new Context], - 'Simple bare token' => ['OOK', (new Context)->searchTerms(["ook"])], - 'Simple negative bare token' => ['-OOK', (new Context)->not->searchTerms(["ook"])], - 'Simple quoted token' => ['"OOK eek"', (new Context)->searchTerms(["ook eek"])], - 'Simple negative quoted token' => ['"-OOK eek"', (new Context)->not->searchTerms(["ook eek"])], - 'Simple bare tokens' => ['OOK eek', (new Context)->searchTerms(["ook", "eek"])], - 'Simple mixed bare tokens' => ['-OOK eek', (new Context)->not->searchTerms(["ook"])->searchTerms(["eek"])], - 'Unclosed quoted token' => ['"OOK eek', (new Context)->searchTerms(["ook eek"])], - 'Unclosed quoted token 2' => ['"OOK eek" "', (new Context)->searchTerms(["ook eek"])], - 'Broken quoted token 1' => ['"-OOK"eek"', (new Context)->not->searchTerms(["ookeek\""])], - 'Broken quoted token 2' => ['""eek"', (new Context)->searchTerms(["eek\""])], - 'Broken quoted token 3' => ['"-"eek"', (new Context)->not->searchTerms(["eek\""])], - 'Empty quoted token' => ['""', new Context], - 'Simple quoted tokens' => ['"OOK eek" "eek ack"', (new Context)->searchTerms(["ook eek", "eek ack"])], - 'Bare blank tag' => [':ook', (new Context)->searchTerms([":ook"])], - 'Quoted blank tag' => ['":ook"', (new Context)->searchTerms([":ook"])], - 'Bare negative blank tag' => ['-:ook', (new Context)->not->searchTerms([":ook"])], - 'Quoted negative blank tag' => ['"-:ook"', (new Context)->not->searchTerms([":ook"])], - 'Bare valueless blank tag' => [':', (new Context)->searchTerms([":"])], - 'Quoted valueless blank tag' => ['":"', (new Context)->searchTerms([":"])], - 'Bare negative valueless blank tag' => ['-:', (new Context)->not->searchTerms([":"])], + 'Blank string' => ["", new Context], + 'Whitespace only' => [" \n \t", new Context], + 'Simple bare token' => ['OOK', (new Context)->searchTerms(["ook"])], + 'Simple negative bare token' => ['-OOK', (new Context)->not->searchTerms(["ook"])], + 'Simple quoted token' => ['"OOK eek"', (new Context)->searchTerms(["ook eek"])], + 'Simple negative quoted token' => ['"-OOK eek"', (new Context)->not->searchTerms(["ook eek"])], + 'Simple bare tokens' => ['OOK eek', (new Context)->searchTerms(["ook", "eek"])], + 'Simple mixed bare tokens' => ['-OOK eek', (new Context)->not->searchTerms(["ook"])->searchTerms(["eek"])], + 'Unclosed quoted token' => ['"OOK eek', (new Context)->searchTerms(["ook eek"])], + 'Unclosed quoted token 2' => ['"OOK eek" "', (new Context)->searchTerms(["ook eek"])], + 'Broken quoted token 1' => ['"-OOK"eek"', (new Context)->not->searchTerms(["ookeek\""])], + 'Broken quoted token 2' => ['""eek"', (new Context)->searchTerms(["eek\""])], + 'Broken quoted token 3' => ['"-"eek"', (new Context)->not->searchTerms(["eek\""])], + 'Empty quoted token' => ['""', new Context], + 'Simple quoted tokens' => ['"OOK eek" "eek ack"', (new Context)->searchTerms(["ook eek", "eek ack"])], + 'Bare blank tag' => [':ook', (new Context)->searchTerms([":ook"])], + 'Quoted blank tag' => ['":ook"', (new Context)->searchTerms([":ook"])], + 'Bare negative blank tag' => ['-:ook', (new Context)->not->searchTerms([":ook"])], + 'Quoted negative blank tag' => ['"-:ook"', (new Context)->not->searchTerms([":ook"])], + 'Bare valueless blank tag' => [':', (new Context)->searchTerms([":"])], + 'Quoted valueless blank tag' => ['":"', (new Context)->searchTerms([":"])], + 'Bare negative valueless blank tag' => ['-:', (new Context)->not->searchTerms([":"])], 'Quoted negative valueless blank tag' => ['"-:"', (new Context)->not->searchTerms([":"])], - 'Double negative' => ['--eek', (new Context)->not->searchTerms(["-eek"])], - 'Double negative 2' => ['--@eek', (new Context)->not->searchTerms(["-@eek"])], - 'Double negative 3' => ['"--@eek"', (new Context)->not->searchTerms(["-@eek"])], - 'Double negative 4' => ['"--eek"', (new Context)->not->searchTerms(["-eek"])], - 'Negative before quote' => ['-"ook"', (new Context)->not->searchTerms(["\"ook\""])], - 'Bare unread tag true' => ['UNREAD:true', (new Context)->unread(true)], - 'Bare unread tag false' => ['UNREAD:false', (new Context)->unread(false)], - 'Bare negative unread tag true' => ['-unread:true', (new Context)->unread(false)], - 'Bare negative unread tag false' => ['-unread:false', (new Context)->unread(true)], - 'Quoted unread tag true' => ['"UNREAD:true"', (new Context)->unread(true)], - 'Quoted unread tag false' => ['"UNREAD:false"', (new Context)->unread(false)], - 'Quoted negative unread tag true' => ['"-unread:true"', (new Context)->unread(false)], - 'Quoted negative unread tag false' => ['"-unread:false"', (new Context)->unread(true)], - 'Bare star tag true' => ['STAR:true', (new Context)->starred(true)], - 'Bare star tag false' => ['STAR:false', (new Context)->starred(false)], - 'Bare negative star tag true' => ['-star:true', (new Context)->starred(false)], - 'Bare negative star tag false' => ['-star:false', (new Context)->starred(true)], - 'Quoted star tag true' => ['"STAR:true"', (new Context)->starred(true)], - 'Quoted star tag false' => ['"STAR:false"', (new Context)->starred(false)], - 'Quoted negative star tag true' => ['"-star:true"', (new Context)->starred(false)], - 'Quoted negative star tag false' => ['"-star:false"', (new Context)->starred(true)], - 'Bare note tag true' => ['NOTE:true', (new Context)->annotated(true)], - 'Bare note tag false' => ['NOTE:false', (new Context)->annotated(false)], - 'Bare negative note tag true' => ['-note:true', (new Context)->annotated(false)], - 'Bare negative note tag false' => ['-note:false', (new Context)->annotated(true)], - 'Quoted note tag true' => ['"NOTE:true"', (new Context)->annotated(true)], - 'Quoted note tag false' => ['"NOTE:false"', (new Context)->annotated(false)], - 'Quoted negative note tag true' => ['"-note:true"', (new Context)->annotated(false)], - 'Quoted negative note tag false' => ['"-note:false"', (new Context)->annotated(true)], - 'Bare pub tag true' => ['PUB:true', null], - 'Bare pub tag false' => ['PUB:false', new Context], - 'Bare negative pub tag true' => ['-pub:true', new Context], - 'Bare negative pub tag false' => ['-pub:false', null], - 'Quoted pub tag true' => ['"PUB:true"', null], - 'Quoted pub tag false' => ['"PUB:false"', new Context], - 'Quoted negative pub tag true' => ['"-pub:true"', new Context], - 'Quoted negative pub tag false' => ['"-pub:false"', null], - 'Non-boolean unread tag' => ['unread:maybe', (new Context)->searchTerms(["unread:maybe"])], - 'Non-boolean star tag' => ['star:maybe', (new Context)->searchTerms(["star:maybe"])], - 'Non-boolean pub tag' => ['pub:maybe', (new Context)->searchTerms(["pub:maybe"])], - 'Non-boolean note tag' => ['note:maybe', (new Context)->annotationTerms(["maybe"])], - 'Valueless unread tag' => ['unread:', (new Context)->searchTerms(["unread:"])], - 'Valueless star tag' => ['star:', (new Context)->searchTerms(["star:"])], - 'Valueless pub tag' => ['pub:', (new Context)->searchTerms(["pub:"])], - 'Valueless note tag' => ['note:', (new Context)->searchTerms(["note:"])], - 'Valueless title tag' => ['title:', (new Context)->searchTerms(["title:"])], - 'Valueless author tag' => ['author:', (new Context)->searchTerms(["author:"])], - 'Escaped quote 1' => ['"""I say, Jeeves!"""', (new Context)->searchTerms(["\"i say, jeeves!\""])], - 'Escaped quote 2' => ['"\\"I say, Jeeves!\\""', (new Context)->searchTerms(["\"i say, jeeves!\""])], - 'Escaped quote 3' => ['\\"I say, Jeeves!\\"', (new Context)->searchTerms(["\\\"i", "say,", "jeeves!\\\""])], - 'Escaped quote 4' => ['"\\"\\I say, Jeeves!\\""', (new Context)->searchTerms(["\"\\i say, jeeves!\""])], - 'Escaped quote 5' => ['"\\I say, Jeeves!"', (new Context)->searchTerms(["\\i say, jeeves!"])], - 'Escaped quote 6' => ['"\\"I say, Jeeves!\\', (new Context)->searchTerms(["\"i say, jeeves!\\"])], - 'Escaped quote 7' => ['"\\', (new Context)->searchTerms(["\\"])], - 'Quoted author tag 1' => ['"author:Neal Stephenson"', (new Context)->authorTerms(["neal stephenson"])], - 'Quoted author tag 2' => ['"author:Jo ""Cap\'n Tripps"" Ashburn"', (new Context)->authorTerms(["jo \"cap'n tripps\" ashburn"])], - 'Quoted author tag 3' => ['"author:Jo \\"Cap\'n Tripps\\" Ashburn"', (new Context)->authorTerms(["jo \"cap'n tripps\" ashburn"])], - 'Quoted author tag 4' => ['"author:Jo ""Cap\'n Tripps"Ashburn"', (new Context)->authorTerms(["jo \"cap'n trippsashburn\""])], - 'Quoted author tag 5' => ['"author:Jo ""Cap\'n Tripps\ Ashburn"', (new Context)->authorTerms(["jo \"cap'n tripps\\ ashburn"])], - 'Quoted author tag 6' => ['"author:Neal Stephenson\\', (new Context)->authorTerms(["neal stephenson\\"])], - 'Quoted title tag' => ['"title:Generic title"', (new Context)->titleTerms(["generic title"])], - 'Contradictory booleans' => ['unread:true -unread:true', null], - 'Doubled boolean' => ['unread:true unread:true', (new Context)->unread(true)], - 'Bare blank date' => ['@', new Context], - 'Quoted blank date' => ['"@"', new Context], - 'Bare ISO date' => ['@2019-03-01', (new Context)->modifiedSince("2019-03-01T00:00:00Z")->notModifiedSince("2019-03-01T23:59:59Z")], - 'Quoted ISO date' => ['"@March 1st, 2019"', (new Context)->modifiedSince("2019-03-01T00:00:00Z")->notModifiedSince("2019-03-01T23:59:59Z")], - 'Bare negative ISO date' => ['-@2019-03-01', (new Context)->not->modifiedSince("2019-03-01T00:00:00Z")->not->notModifiedSince("2019-03-01T23:59:59Z")], - 'Quoted negative English date' => ['"-@March 1st, 2019"', (new Context)->not->modifiedSince("2019-03-01T00:00:00Z")->not->notModifiedSince("2019-03-01T23:59:59Z")], - 'Invalid date' => ['@Bugaboo', new Context], - 'Escaped quoted date 1' => ['"@""Yesterday" and today', (new Context)->searchTerms(["and", "today"])], - 'Escaped quoted date 2' => ['"@\\"Yesterday" and today', (new Context)->searchTerms(["and", "today"])], - 'Escaped quoted date 3' => ['"@Yesterday\\', new Context], - 'Escaped quoted date 4' => ['"@Yesterday\\and today', new Context], - 'Escaped quoted date 5' => ['"@Yesterday"and today', (new Context)->searchTerms(["today"])], - 'Contradictory dates' => ['@Yesterday @Today', null], - 'Doubled date' => ['"@March 1st, 2019" @2019-03-01', (new Context)->modifiedSince("2019-03-01T00:00:00Z")->notModifiedSince("2019-03-01T23:59:59Z")], - 'Doubled negative date' => ['"-@March 1st, 2019" -@2019-03-01', (new Context)->not->modifiedSince("2019-03-01T00:00:00Z")->not->notModifiedSince("2019-03-01T23:59:59Z")], + 'Double negative' => ['--eek', (new Context)->not->searchTerms(["-eek"])], + 'Double negative 2' => ['--@eek', (new Context)->not->searchTerms(["-@eek"])], + 'Double negative 3' => ['"--@eek"', (new Context)->not->searchTerms(["-@eek"])], + 'Double negative 4' => ['"--eek"', (new Context)->not->searchTerms(["-eek"])], + 'Negative before quote' => ['-"ook"', (new Context)->not->searchTerms(["\"ook\""])], + 'Bare unread tag true' => ['UNREAD:true', (new Context)->unread(true)], + 'Bare unread tag false' => ['UNREAD:false', (new Context)->unread(false)], + 'Bare negative unread tag true' => ['-unread:true', (new Context)->unread(false)], + 'Bare negative unread tag false' => ['-unread:false', (new Context)->unread(true)], + 'Quoted unread tag true' => ['"UNREAD:true"', (new Context)->unread(true)], + 'Quoted unread tag false' => ['"UNREAD:false"', (new Context)->unread(false)], + 'Quoted negative unread tag true' => ['"-unread:true"', (new Context)->unread(false)], + 'Quoted negative unread tag false' => ['"-unread:false"', (new Context)->unread(true)], + 'Bare star tag true' => ['STAR:true', (new Context)->starred(true)], + 'Bare star tag false' => ['STAR:false', (new Context)->starred(false)], + 'Bare negative star tag true' => ['-star:true', (new Context)->starred(false)], + 'Bare negative star tag false' => ['-star:false', (new Context)->starred(true)], + 'Quoted star tag true' => ['"STAR:true"', (new Context)->starred(true)], + 'Quoted star tag false' => ['"STAR:false"', (new Context)->starred(false)], + 'Quoted negative star tag true' => ['"-star:true"', (new Context)->starred(false)], + 'Quoted negative star tag false' => ['"-star:false"', (new Context)->starred(true)], + 'Bare note tag true' => ['NOTE:true', (new Context)->annotated(true)], + 'Bare note tag false' => ['NOTE:false', (new Context)->annotated(false)], + 'Bare negative note tag true' => ['-note:true', (new Context)->annotated(false)], + 'Bare negative note tag false' => ['-note:false', (new Context)->annotated(true)], + 'Quoted note tag true' => ['"NOTE:true"', (new Context)->annotated(true)], + 'Quoted note tag false' => ['"NOTE:false"', (new Context)->annotated(false)], + 'Quoted negative note tag true' => ['"-note:true"', (new Context)->annotated(false)], + 'Quoted negative note tag false' => ['"-note:false"', (new Context)->annotated(true)], + 'Bare pub tag true' => ['PUB:true', null], + 'Bare pub tag false' => ['PUB:false', new Context], + 'Bare negative pub tag true' => ['-pub:true', new Context], + 'Bare negative pub tag false' => ['-pub:false', null], + 'Quoted pub tag true' => ['"PUB:true"', null], + 'Quoted pub tag false' => ['"PUB:false"', new Context], + 'Quoted negative pub tag true' => ['"-pub:true"', new Context], + 'Quoted negative pub tag false' => ['"-pub:false"', null], + 'Non-boolean unread tag' => ['unread:maybe', (new Context)->searchTerms(["unread:maybe"])], + 'Non-boolean star tag' => ['star:maybe', (new Context)->searchTerms(["star:maybe"])], + 'Non-boolean pub tag' => ['pub:maybe', (new Context)->searchTerms(["pub:maybe"])], + 'Non-boolean note tag' => ['note:maybe', (new Context)->annotationTerms(["maybe"])], + 'Valueless unread tag' => ['unread:', (new Context)->searchTerms(["unread:"])], + 'Valueless star tag' => ['star:', (new Context)->searchTerms(["star:"])], + 'Valueless pub tag' => ['pub:', (new Context)->searchTerms(["pub:"])], + 'Valueless note tag' => ['note:', (new Context)->searchTerms(["note:"])], + 'Valueless title tag' => ['title:', (new Context)->searchTerms(["title:"])], + 'Valueless author tag' => ['author:', (new Context)->searchTerms(["author:"])], + 'Escaped quote 1' => ['"""I say, Jeeves!"""', (new Context)->searchTerms(["\"i say, jeeves!\""])], + 'Escaped quote 2' => ['"\\"I say, Jeeves!\\""', (new Context)->searchTerms(["\"i say, jeeves!\""])], + 'Escaped quote 3' => ['\\"I say, Jeeves!\\"', (new Context)->searchTerms(["\\\"i", "say,", "jeeves!\\\""])], + 'Escaped quote 4' => ['"\\"\\I say, Jeeves!\\""', (new Context)->searchTerms(["\"\\i say, jeeves!\""])], + 'Escaped quote 5' => ['"\\I say, Jeeves!"', (new Context)->searchTerms(["\\i say, jeeves!"])], + 'Escaped quote 6' => ['"\\"I say, Jeeves!\\', (new Context)->searchTerms(["\"i say, jeeves!\\"])], + 'Escaped quote 7' => ['"\\', (new Context)->searchTerms(["\\"])], + 'Quoted author tag 1' => ['"author:Neal Stephenson"', (new Context)->authorTerms(["neal stephenson"])], + 'Quoted author tag 2' => ['"author:Jo ""Cap\'n Tripps"" Ashburn"', (new Context)->authorTerms(["jo \"cap'n tripps\" ashburn"])], + 'Quoted author tag 3' => ['"author:Jo \\"Cap\'n Tripps\\" Ashburn"', (new Context)->authorTerms(["jo \"cap'n tripps\" ashburn"])], + 'Quoted author tag 4' => ['"author:Jo ""Cap\'n Tripps"Ashburn"', (new Context)->authorTerms(["jo \"cap'n trippsashburn\""])], + 'Quoted author tag 5' => ['"author:Jo ""Cap\'n Tripps\ Ashburn"', (new Context)->authorTerms(["jo \"cap'n tripps\\ ashburn"])], + 'Quoted author tag 6' => ['"author:Neal Stephenson\\', (new Context)->authorTerms(["neal stephenson\\"])], + 'Quoted title tag' => ['"title:Generic title"', (new Context)->titleTerms(["generic title"])], + 'Contradictory booleans' => ['unread:true -unread:true', null], + 'Doubled boolean' => ['unread:true unread:true', (new Context)->unread(true)], + 'Bare blank date' => ['@', new Context], + 'Quoted blank date' => ['"@"', new Context], + 'Bare ISO date' => ['@2019-03-01', (new Context)->modifiedSince("2019-03-01T00:00:00Z")->notModifiedSince("2019-03-01T23:59:59Z")], + 'Quoted ISO date' => ['"@March 1st, 2019"', (new Context)->modifiedSince("2019-03-01T00:00:00Z")->notModifiedSince("2019-03-01T23:59:59Z")], + 'Bare negative ISO date' => ['-@2019-03-01', (new Context)->not->modifiedSince("2019-03-01T00:00:00Z")->not->notModifiedSince("2019-03-01T23:59:59Z")], + 'Quoted negative English date' => ['"-@March 1st, 2019"', (new Context)->not->modifiedSince("2019-03-01T00:00:00Z")->not->notModifiedSince("2019-03-01T23:59:59Z")], + 'Invalid date' => ['@Bugaboo', new Context], + 'Escaped quoted date 1' => ['"@""Yesterday" and today', (new Context)->searchTerms(["and", "today"])], + 'Escaped quoted date 2' => ['"@\\"Yesterday" and today', (new Context)->searchTerms(["and", "today"])], + 'Escaped quoted date 3' => ['"@Yesterday\\', new Context], + 'Escaped quoted date 4' => ['"@Yesterday\\and today', new Context], + 'Escaped quoted date 5' => ['"@Yesterday"and today', (new Context)->searchTerms(["today"])], + 'Contradictory dates' => ['@Yesterday @Today', null], + 'Doubled date' => ['"@March 1st, 2019" @2019-03-01', (new Context)->modifiedSince("2019-03-01T00:00:00Z")->notModifiedSince("2019-03-01T23:59:59Z")], + 'Doubled negative date' => ['"-@March 1st, 2019" -@2019-03-01', (new Context)->not->modifiedSince("2019-03-01T00:00:00Z")->not->notModifiedSince("2019-03-01T23:59:59Z")], ]; } diff --git a/tests/cases/Service/TestSubprocess.php b/tests/cases/Service/TestSubprocess.php index f5c3a37..b6ca047 100644 --- a/tests/cases/Service/TestSubprocess.php +++ b/tests/cases/Service/TestSubprocess.php @@ -7,7 +7,6 @@ declare(strict_types=1); namespace JKingWeb\Arsse\TestCase\Service; use JKingWeb\Arsse\Arsse; -use JKingWeb\Arsse\Database; use JKingWeb\Arsse\Service\Driver as DriverInterface; use JKingWeb\Arsse\Service\Subprocess\Driver; diff --git a/tests/cases/TestArsse.php b/tests/cases/TestArsse.php index edb7e12..a15a800 100644 --- a/tests/cases/TestArsse.php +++ b/tests/cases/TestArsse.php @@ -11,7 +11,6 @@ use JKingWeb\Arsse\Conf; use JKingWeb\Arsse\Lang; use JKingWeb\Arsse\User; use JKingWeb\Arsse\Database; -use JKingWeb\Arsse\Service; /** @covers \JKingWeb\Arsse\Arsse */ class TestArsse extends \JKingWeb\Arsse\Test\AbstractTest { diff --git a/tests/cases/User/TestInternal.php b/tests/cases/User/TestInternal.php index 4b9cfb8..4333771 100644 --- a/tests/cases/User/TestInternal.php +++ b/tests/cases/User/TestInternal.php @@ -32,7 +32,7 @@ class TestInternal extends \JKingWeb\Arsse\Test\AbstractTest { /** * @dataProvider provideAuthentication * @group slow - */ + */ public function testAuthenticateAUser(bool $authorized, string $user, $password, bool $exp): void { if ($authorized) { \Phake::when(Arsse::$db)->userPasswordGet("john.doe@example.com")->thenReturn('$2y$10$1zbqRJhxM8uUjeSBPp4IhO90xrqK0XjEh9Z16iIYEFRV4U.zeAFom'); // hash of "secret" diff --git a/tests/cases/User/TestUser.php b/tests/cases/User/TestUser.php index df31c59..93b5ee7 100644 --- a/tests/cases/User/TestUser.php +++ b/tests/cases/User/TestUser.php @@ -147,7 +147,7 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest { $calls = 2; } } else { - $calls = 4; + $calls = 4; } try { $pass1 = $u->add($user, null); @@ -255,7 +255,7 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest { $calls = 2; } } else { - $calls = 4; + $calls = 4; } try { $pass1 = $u->passwordSet($user, null); diff --git a/tests/docroot/Feed/Caching/304Conditional.php b/tests/docroot/Feed/Caching/304Conditional.php index 6b2002f..42b4a5a 100644 --- a/tests/docroot/Feed/Caching/304Conditional.php +++ b/tests/docroot/Feed/Caching/304Conditional.php @@ -14,8 +14,8 @@ if ( } else { return [ 'code' => 304, - 'lastMod' => random_int(0, 2^31), - 'fields' => [ + 'lastMod' => random_int(0, 2 ^ 31), + 'fields' => [ "ETag: ".bin2hex(random_bytes(8)), ], ]; diff --git a/tests/docroot/Feed/Caching/304Random.php b/tests/docroot/Feed/Caching/304Random.php index f444eb8..29b2bdd 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), - 'fields' => [ + 'lastMod' => random_int(0, 2 ^ 31), + 'fields' => [ "ETag: ".bin2hex(random_bytes(8)), ], ]; diff --git a/tests/docroot/Feed/Fetching/EndlessLoop.php b/tests/docroot/Feed/Fetching/EndlessLoop.php index e13f504..e9296f3 100644 --- a/tests/docroot/Feed/Fetching/EndlessLoop.php +++ b/tests/docroot/Feed/Fetching/EndlessLoop.php @@ -3,5 +3,5 @@ 'cache' => false, 'fields' => [ 'Location: http://localhost:'.$_SERVER['SERVER_PORT'].$_SERVER['REQUEST_URI']."0", - ] + ], ]; diff --git a/tests/lib/AbstractTest.php b/tests/lib/AbstractTest.php index 1a03278..ed17243 100644 --- a/tests/lib/AbstractTest.php +++ b/tests/lib/AbstractTest.php @@ -70,7 +70,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { protected function serverRequest(string $method, string $url, string $urlPrefix, array $headers = [], array $vars = [], $body = null, string $type = "", $params = [], string $user = null): ServerRequestInterface { $server = [ 'REQUEST_METHOD' => $method, - 'REQUEST_URI' => $url, + 'REQUEST_URI' => $url, ]; if (strlen($type)) { $server['HTTP_CONTENT_TYPE'] = $type; @@ -109,7 +109,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { $req = $req->withAttribute("authenticationFailed", true); } } - if (strlen($type) &&strlen($body ?? "")) { + if (strlen($type) && strlen($body ?? "")) { $req = $req->withHeader("Content-Type", $type); } foreach ($headers as $key => $value) { @@ -135,8 +135,8 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { $this->expectException(get_class($msg)); $this->expectExceptionCode($msg->getCode()); } else { - $class = \JKingWeb\Arsse\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type; - $msgID = ($prefix !== "" ? $prefix . "/" : "") . $type. ".$msg"; + $class = \JKingWeb\Arsse\NS_BASE.($prefix !== "" ? str_replace("/", "\\", $prefix)."\\" : "").$type; + $msgID = ($prefix !== "" ? $prefix."/" : "").$type.".$msg"; if (array_key_exists($msgID, Exception::CODES)) { $code = Exception::CODES[$msgID]; } else { @@ -177,7 +177,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { public function assertTime($exp, $test, string $msg = ''): void { $test = $this->approximateTime($exp, $test); - $exp = Date::transform($exp, "iso8601"); + $exp = Date::transform($exp, "iso8601"); $test = Date::transform($test, "iso8601"); $this->assertSame($exp, $test, $msg); } @@ -260,7 +260,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { break; } } - if ($row===$test) { + if ($row === $test) { $data[$index] = $test; break; } diff --git a/tests/lib/DatabaseDrivers/MySQL.php b/tests/lib/DatabaseDrivers/MySQL.php index c0863b7..f1571a2 100644 --- a/tests/lib/DatabaseDrivers/MySQL.php +++ b/tests/lib/DatabaseDrivers/MySQL.php @@ -16,7 +16,7 @@ trait MySQL { protected static $dbStatementClass = \JKingWeb\Arsse\Db\MySQL\Statement::class; protected static $dbDriverClass = \JKingWeb\Arsse\Db\MySQL\Driver::class; protected static $stringOutput = true; - + public static function dbInterface() { $d = @new \mysqli(Arsse::$conf->dbMySQLHost, Arsse::$conf->dbMySQLUser, Arsse::$conf->dbMySQLPass, Arsse::$conf->dbMySQLDb, Arsse::$conf->dbMySQLPort); if ($d->connect_errno) { @@ -28,7 +28,7 @@ trait MySQL { } return $d; } - + public static function dbTableList($db): array { $listTables = "SELECT table_name as name from information_schema.tables where table_schema = database() and table_name like 'arsse_%'"; if ($db instanceof Driver) { diff --git a/tests/lib/DatabaseDrivers/MySQLPDO.php b/tests/lib/DatabaseDrivers/MySQLPDO.php index 0b9ffef..bbaf8ab 100644 --- a/tests/lib/DatabaseDrivers/MySQLPDO.php +++ b/tests/lib/DatabaseDrivers/MySQLPDO.php @@ -7,7 +7,6 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Test\DatabaseDrivers; use JKingWeb\Arsse\Arsse; -use JKingWeb\Arsse\Db\Driver; trait MySQLPDO { protected static $implementation = "PDO MySQL"; @@ -16,22 +15,22 @@ trait MySQLPDO { protected static $dbStatementClass = \JKingWeb\Arsse\Db\MySQL\PDOStatement::class; protected static $dbDriverClass = \JKingWeb\Arsse\Db\MySQL\PDODriver::class; protected static $stringOutput = true; - + public static function dbInterface() { try { $dsn = []; $params = [ 'charset' => "utf8mb4", - 'host' => Arsse::$conf->dbMySQLHost, - 'port' => Arsse::$conf->dbMySQLPort, - 'dbname' => Arsse::$conf->dbMySQLDb, + 'host' => Arsse::$conf->dbMySQLHost, + 'port' => Arsse::$conf->dbMySQLPort, + 'dbname' => Arsse::$conf->dbMySQLDb, ]; foreach ($params as $k => $v) { $dsn[] = "$k=$v"; } $dsn = "mysql:".implode(";", $dsn); $d = new \PDO($dsn, Arsse::$conf->dbMySQLUser, Arsse::$conf->dbMySQLPass, [ - \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::MYSQL_ATTR_MULTI_STATEMENTS => false, ]); foreach (\JKingWeb\Arsse\Db\MySQL\PDODriver::makeSetupQueries() as $q) { @@ -42,7 +41,7 @@ trait MySQLPDO { return; } } - + public static function dbTableList($db): array { return MySQL::dbTableList($db); } diff --git a/tests/lib/DatabaseDrivers/PostgreSQL.php b/tests/lib/DatabaseDrivers/PostgreSQL.php index 3b59ee8..fb0038c 100644 --- a/tests/lib/DatabaseDrivers/PostgreSQL.php +++ b/tests/lib/DatabaseDrivers/PostgreSQL.php @@ -16,7 +16,7 @@ trait PostgreSQL { protected static $dbStatementClass = \JKingWeb\Arsse\Db\PostgreSQL\Statement::class; protected static $dbDriverClass = \JKingWeb\Arsse\Db\PostgreSQL\Driver::class; protected static $stringOutput = true; - + public static function dbInterface() { $connString = \JKingWeb\Arsse\Db\PostgreSQL\Driver::makeConnectionString(false, Arsse::$conf->dbPostgreSQLUser, Arsse::$conf->dbPostgreSQLPass, Arsse::$conf->dbPostgreSQLDb, Arsse::$conf->dbPostgreSQLHost, Arsse::$conf->dbPostgreSQLPort, ""); if ($d = @pg_connect($connString, \PGSQL_CONNECT_FORCE_NEW)) { @@ -38,7 +38,7 @@ trait PostgreSQL { pg_query($db, $q); } } - + public static function dbTableList($db): array { $listObjects = "SELECT table_name as name, 'TABLE' as type from information_schema.tables where table_schema = current_schema() and table_name like 'arsse_%' union SELECT collation_name as name, 'COLLATION' as type from information_schema.collations where collation_schema = current_schema()"; if ($db instanceof Driver) { diff --git a/tests/lib/DatabaseDrivers/PostgreSQLPDO.php b/tests/lib/DatabaseDrivers/PostgreSQLPDO.php index b7f5f25..58001b6 100644 --- a/tests/lib/DatabaseDrivers/PostgreSQLPDO.php +++ b/tests/lib/DatabaseDrivers/PostgreSQLPDO.php @@ -15,7 +15,7 @@ trait PostgreSQLPDO { protected static $dbStatementClass = \JKingWeb\Arsse\Db\PostgreSQL\PDOStatement::class; protected static $dbDriverClass = \JKingWeb\Arsse\Db\PostgreSQL\PDODriver::class; protected static $stringOutput = false; - + public static function dbInterface() { $connString = \JKingWeb\Arsse\Db\PostgreSQL\Driver::makeConnectionString(true, Arsse::$conf->dbPostgreSQLUser, Arsse::$conf->dbPostgreSQLPass, Arsse::$conf->dbPostgreSQLDb, Arsse::$conf->dbPostgreSQLHost, Arsse::$conf->dbPostgreSQLPort, ""); try { @@ -28,7 +28,7 @@ trait PostgreSQLPDO { } return $d; } - + public static function dbTableList($db): array { return PostgreSQL::dbTableList($db); } diff --git a/tests/lib/DatabaseDrivers/SQLite3.php b/tests/lib/DatabaseDrivers/SQLite3.php index 20f50cc..7063372 100644 --- a/tests/lib/DatabaseDrivers/SQLite3.php +++ b/tests/lib/DatabaseDrivers/SQLite3.php @@ -16,7 +16,7 @@ trait SQLite3 { protected static $dbStatementClass = \JKingWeb\Arsse\Db\SQLite3\Statement::class; protected static $dbDriverClass = \JKingWeb\Arsse\Db\SQLite3\Driver::class; protected static $stringOutput = false; - + protected static function dbInterface() { try { $d = new \SQLite3(Arsse::$conf->dbSQLite3File); @@ -26,7 +26,7 @@ trait SQLite3 { $d->enableExceptions(true); return $d; } - + public static function dbTableList($db): array { $listTables = "SELECT name from sqlite_master where type = 'table' and name like 'arsse^_%' escape '^'"; if ($db instanceof Driver) { diff --git a/tests/lib/DatabaseDrivers/SQLite3PDO.php b/tests/lib/DatabaseDrivers/SQLite3PDO.php index c7af207..0a81eb8 100644 --- a/tests/lib/DatabaseDrivers/SQLite3PDO.php +++ b/tests/lib/DatabaseDrivers/SQLite3PDO.php @@ -15,7 +15,7 @@ trait SQLite3PDO { protected static $dbStatementClass = \JKingWeb\Arsse\Db\SQLite3\PDOStatement::class; protected static $dbDriverClass = \JKingWeb\Arsse\Db\SQLite3\PDODriver::class; protected static $stringOutput = true; - + public static function dbInterface() { try { $d = new \PDO("sqlite:".Arsse::$conf->dbSQLite3File, "", "", [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]); @@ -25,7 +25,7 @@ trait SQLite3PDO { return; } } - + public static function dbTableList($db): array { return SQLite3::dbTableList($db); } diff --git a/tests/server.php b/tests/server.php index df9f28e..2d738c9 100644 --- a/tests/server.php +++ b/tests/server.php @@ -29,7 +29,6 @@ which include the following data: */ - ignore_user_abort(false); ob_start(); $defaults = [ // default values for response