mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
Passed code through linter
This commit is contained in:
parent
28201ba573
commit
f7e50fe95d
145 changed files with 1728 additions and 1556 deletions
25
.php_cs.dist
Normal file
25
.php_cs.dist
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
|
require_once __DIR__.DIRECTORY_SEPARATOR."bootstrap.php";
|
||||||
|
|
||||||
|
$paths = [
|
||||||
|
__FILE__,
|
||||||
|
BASE."arsse.php",
|
||||||
|
BASE."lib",
|
||||||
|
BASE."tests",
|
||||||
|
];
|
||||||
|
$rules = [
|
||||||
|
'@PSR2' => true,
|
||||||
|
'braces' => ['position_after_functions_and_oop_constructs' => "same"],
|
||||||
|
];
|
||||||
|
|
||||||
|
$finder = \PhpCsFixer\Finder::create();
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
if (is_file($path)) {
|
||||||
|
$finder = $finder->path($path);
|
||||||
|
} else {
|
||||||
|
$finder = $finder->in($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return \PhpCsFixer\Config::create()->setRules($rules)->setFinder($finder);
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
require_once __DIR__.DIRECTORY_SEPARATOR."bootstrap.php";
|
require_once __DIR__.DIRECTORY_SEPARATOR."bootstrap.php";
|
||||||
|
|
||||||
if (\PHP_SAPI=="cli") {
|
if (\PHP_SAPI=="cli") {
|
||||||
|
|
|
@ -3,7 +3,6 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
abstract class AbstractException extends \Exception {
|
abstract class AbstractException extends \Exception {
|
||||||
|
|
||||||
const CODES = [
|
const CODES = [
|
||||||
"Exception.uncoded" => -1,
|
"Exception.uncoded" => -1,
|
||||||
"Exception.unknown" => 10000,
|
"Exception.unknown" => 10000,
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Arsse {
|
||||||
/** @var User */
|
/** @var User */
|
||||||
public static $user;
|
public static $user;
|
||||||
|
|
||||||
static function load(Conf $conf) {
|
public static function load(Conf $conf) {
|
||||||
static::$lang = new Lang();
|
static::$lang = new Lang();
|
||||||
static::$conf = $conf;
|
static::$conf = $conf;
|
||||||
static::$lang->set($conf->lang);
|
static::$lang->set($conf->lang);
|
||||||
|
|
12
lib/CLI.php
12
lib/CLI.php
|
@ -22,7 +22,7 @@ configuration to a sample file.
|
||||||
USAGE_TEXT;
|
USAGE_TEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
function __construct(array $argv = null) {
|
public function __construct(array $argv = null) {
|
||||||
if (is_null($argv)) {
|
if (is_null($argv)) {
|
||||||
$argv = array_slice($_SERVER['argv'], 1);
|
$argv = array_slice($_SERVER['argv'], 1);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ USAGE_TEXT;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dispatch(array $args = null): int {
|
public function dispatch(array $args = null): int {
|
||||||
// act on command line
|
// act on command line
|
||||||
if (is_null($args)) {
|
if (is_null($args)) {
|
||||||
$args = $this->args;
|
$args = $this->args;
|
||||||
|
@ -72,20 +72,20 @@ USAGE_TEXT;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function daemon(bool $loop = true): int {
|
public function daemon(bool $loop = true): int {
|
||||||
(new Service)->watch($loop);
|
(new Service)->watch($loop);
|
||||||
return 0; // FIXME: should return the exception code of thrown exceptions
|
return 0; // FIXME: should return the exception code of thrown exceptions
|
||||||
}
|
}
|
||||||
|
|
||||||
function feedRefresh(int $id): int {
|
public function feedRefresh(int $id): int {
|
||||||
return (int) !Arsse::$db->feedUpdate($id); // FIXME: exception error codes should be returned here
|
return (int) !Arsse::$db->feedUpdate($id); // FIXME: exception error codes should be returned here
|
||||||
}
|
}
|
||||||
|
|
||||||
function confSaveDefaults(string $file): int {
|
public function confSaveDefaults(string $file): int {
|
||||||
return (int) !(new Conf)->exportFile($file, true);
|
return (int) !(new Conf)->exportFile($file, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userAdd(string $user, string $password = null): int {
|
public function userAdd(string $user, string $password = null): int {
|
||||||
$passwd = Arsse::$user->add($user, $password);
|
$passwd = Arsse::$user->add($user, $password);
|
||||||
if (is_null($password)) {
|
if (is_null($password)) {
|
||||||
echo $passwd;
|
echo $passwd;
|
||||||
|
|
|
@ -138,7 +138,8 @@ class Conf {
|
||||||
// retrieve the property's docblock, if it exists
|
// retrieve the property's docblock, if it exists
|
||||||
try {
|
try {
|
||||||
$doc = (new \ReflectionProperty(self::class, $prop))->getDocComment();
|
$doc = (new \ReflectionProperty(self::class, $prop))->getDocComment();
|
||||||
} catch(\ReflectionException $e) {}
|
} catch (\ReflectionException $e) {
|
||||||
|
}
|
||||||
if ($doc) {
|
if ($doc) {
|
||||||
// parse the docblock to extract the property description
|
// parse the docblock to extract the property description
|
||||||
if (preg_match("<@var\s+\S+\s+(.+?)(?:\s*\*/)?$>m", $doc, $match)) {
|
if (preg_match("<@var\s+\S+\s+(.+?)(?:\s*\*/)?$>m", $doc, $match)) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use PasswordGenerator\Generator as PassGen;
|
use PasswordGenerator\Generator as PassGen;
|
||||||
use JKingWeb\Arsse\Misc\Query;
|
use JKingWeb\Arsse\Misc\Query;
|
||||||
use JKingWeb\Arsse\Misc\Context;
|
use JKingWeb\Arsse\Misc\Context;
|
||||||
|
@ -25,7 +26,7 @@ class Database {
|
||||||
return debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function'];
|
return debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function'];
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function driverList(): array {
|
public static function driverList(): array {
|
||||||
$sep = \DIRECTORY_SEPARATOR;
|
$sep = \DIRECTORY_SEPARATOR;
|
||||||
$path = __DIR__.$sep."Db".$sep;
|
$path = __DIR__.$sep."Db".$sep;
|
||||||
$classes = [];
|
$classes = [];
|
||||||
|
|
|
@ -7,9 +7,9 @@ abstract class AbstractDriver implements Driver {
|
||||||
protected $transDepth = 0;
|
protected $transDepth = 0;
|
||||||
protected $transStatus = [];
|
protected $transStatus = [];
|
||||||
|
|
||||||
public abstract function prepareArray(string $query, array $paramTypes): Statement;
|
abstract public function prepareArray(string $query, array $paramTypes): Statement;
|
||||||
protected abstract function lock(): bool;
|
abstract protected function lock(): bool;
|
||||||
protected abstract function unlock(bool $rollback = false) : bool;
|
abstract protected function unlock(bool $rollback = false) : bool;
|
||||||
|
|
||||||
/** @codeCoverageIgnore */
|
/** @codeCoverageIgnore */
|
||||||
public function schemaVersion(): int {
|
public function schemaVersion(): int {
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Db;
|
namespace JKingWeb\Arsse\Db;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
|
|
||||||
abstract class AbstractStatement implements Statement {
|
abstract class AbstractStatement implements Statement {
|
||||||
|
|
||||||
protected $types = [];
|
protected $types = [];
|
||||||
protected $isNullable = [];
|
protected $isNullable = [];
|
||||||
protected $values = ['pre' => [], 'post' => []];
|
protected $values = ['pre' => [], 'post' => []];
|
||||||
|
|
||||||
abstract function runArray(array $values = []): Result;
|
abstract public function runArray(array $values = []): Result;
|
||||||
|
|
||||||
public function run(...$values): Result {
|
public function run(...$values): Result {
|
||||||
return $this->runArray($values);
|
return $this->runArray($values);
|
||||||
|
|
|
@ -9,26 +9,26 @@ interface Driver {
|
||||||
const TR_PEND_COMMIT = -1;
|
const TR_PEND_COMMIT = -1;
|
||||||
const TR_PEND_ROLLBACK = -2;
|
const TR_PEND_ROLLBACK = -2;
|
||||||
|
|
||||||
function __construct();
|
public function __construct();
|
||||||
// returns a human-friendly name for the driver (for display in installer, for example)
|
// returns a human-friendly name for the driver (for display in installer, for example)
|
||||||
static function driverName(): string;
|
public static function driverName(): string;
|
||||||
// returns the version of the scheme of the opened database; if uninitialized should return 0
|
// returns the version of the scheme of the opened database; if uninitialized should return 0
|
||||||
function schemaVersion(): int;
|
public function schemaVersion(): int;
|
||||||
// return a Transaction object
|
// return a Transaction object
|
||||||
function begin(bool $lock = false): Transaction;
|
public function begin(bool $lock = false): Transaction;
|
||||||
// manually begin a real or synthetic transactions, with real or synthetic nesting
|
// manually begin a real or synthetic transactions, with real or synthetic nesting
|
||||||
function savepointCreate(): int;
|
public function savepointCreate(): int;
|
||||||
// manually commit either the latest or all pending nested transactions
|
// manually commit either the latest or all pending nested transactions
|
||||||
function savepointRelease(int $index = null): bool;
|
public function savepointRelease(int $index = null): bool;
|
||||||
// manually rollback either the latest or all pending nested transactions
|
// manually rollback either the latest or all pending nested transactions
|
||||||
function savepointUndo(int $index = null): bool;
|
public function savepointUndo(int $index = null): bool;
|
||||||
// attempt to perform an in-place upgrade of the database schema; this may be a no-op which always throws an exception
|
// attempt to perform an in-place upgrade of the database schema; this may be a no-op which always throws an exception
|
||||||
function schemaUpdate(int $to): bool;
|
public function schemaUpdate(int $to): bool;
|
||||||
// execute one or more unsanitized SQL queries and return an indication of success
|
// execute one or more unsanitized SQL queries and return an indication of success
|
||||||
function exec(string $query): bool;
|
public function exec(string $query): bool;
|
||||||
// perform a single unsanitized query and return a result set
|
// perform a single unsanitized query and return a result set
|
||||||
function query(string $query): Result;
|
public function query(string $query): Result;
|
||||||
// ready a prepared statement for later execution
|
// ready a prepared statement for later execution
|
||||||
function prepare(string $query, ...$paramType): Statement;
|
public function prepare(string $query, ...$paramType): Statement;
|
||||||
function prepareArray(string $query, array $paramTypes): Statement;
|
public function prepareArray(string $query, array $paramTypes): Statement;
|
||||||
}
|
}
|
|
@ -3,16 +3,16 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Db;
|
namespace JKingWeb\Arsse\Db;
|
||||||
|
|
||||||
interface Result extends \Iterator {
|
interface Result extends \Iterator {
|
||||||
function current();
|
public function current();
|
||||||
function key();
|
public function key();
|
||||||
function next();
|
public function next();
|
||||||
function rewind();
|
public function rewind();
|
||||||
function valid();
|
public function valid();
|
||||||
|
|
||||||
function getRow();
|
public function getRow();
|
||||||
function getAll(): array;
|
public function getAll(): array;
|
||||||
function getValue();
|
public function getValue();
|
||||||
|
|
||||||
function changes();
|
public function changes();
|
||||||
function lastId();
|
public function lastId();
|
||||||
}
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Db\SQLite3;
|
namespace JKingWeb\Arsse\Db\SQLite3;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Db\Exception;
|
use JKingWeb\Arsse\Db\Exception;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use JKingWeb\Arsse\Db\ExceptionTimeout;
|
use JKingWeb\Arsse\Db\ExceptionTimeout;
|
||||||
|
|
||||||
|
|
||||||
class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
|
class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
|
||||||
use ExceptionBuilder;
|
use ExceptionBuilder;
|
||||||
|
|
||||||
|
@ -64,12 +64,15 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct() {
|
public function __destruct() {
|
||||||
try{$this->db->close();} catch(\Exception $e) {}
|
try {
|
||||||
|
$this->db->close();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
unset($this->db);
|
unset($this->db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static public function driverName(): string {
|
public static function driverName(): string {
|
||||||
return Arsse::$lang->msg("Driver.Db.SQLite3.Name");
|
return Arsse::$lang->msg("Driver.Db.SQLite3.Name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Db\SQLite3;
|
namespace JKingWeb\Arsse\Db\SQLite3;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Db\Exception;
|
use JKingWeb\Arsse\Db\Exception;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use JKingWeb\Arsse\Db\ExceptionTimeout;
|
use JKingWeb\Arsse\Db\ExceptionTimeout;
|
||||||
|
|
||||||
|
|
||||||
trait ExceptionBuilder {
|
trait ExceptionBuilder {
|
||||||
|
|
||||||
public function exceptionBuild() {
|
public function exceptionBuild() {
|
||||||
switch ($this->db->lastErrorCode()) {
|
switch ($this->db->lastErrorCode()) {
|
||||||
case self::SQLITE_BUSY:
|
case self::SQLITE_BUSY:
|
||||||
|
|
|
@ -52,7 +52,10 @@ class Result implements \JKingWeb\Arsse\Db\Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct() {
|
public function __destruct() {
|
||||||
try{$this->set->finalize();} catch(\Throwable $e) {}
|
try {
|
||||||
|
$this->set->finalize();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
}
|
||||||
unset($this->set);
|
unset($this->set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Db\SQLite3;
|
namespace JKingWeb\Arsse\Db\SQLite3;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Db\Exception;
|
use JKingWeb\Arsse\Db\Exception;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use JKingWeb\Arsse\Db\ExceptionTimeout;
|
use JKingWeb\Arsse\Db\ExceptionTimeout;
|
||||||
|
@ -33,7 +34,10 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct() {
|
public function __destruct() {
|
||||||
try {$this->st->close();} catch(\Throwable $e) {}
|
try {
|
||||||
|
$this->st->close();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
}
|
||||||
unset($this->st);
|
unset($this->st);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ interface Statement {
|
||||||
"bit" => "boolean",
|
"bit" => "boolean",
|
||||||
];
|
];
|
||||||
|
|
||||||
function run(...$values): Result;
|
public function run(...$values): Result;
|
||||||
function runArray(array $values = []): Result;
|
public function runArray(array $values = []): Result;
|
||||||
function rebind(...$bindings): bool;
|
public function rebind(...$bindings): bool;
|
||||||
function rebindArray(array $bindings): bool;
|
public function rebindArray(array $bindings): bool;
|
||||||
}
|
}
|
|
@ -7,13 +7,13 @@ class Transaction {
|
||||||
protected $pending = false;
|
protected $pending = false;
|
||||||
protected $drv;
|
protected $drv;
|
||||||
|
|
||||||
function __construct(Driver $drv, bool $lock = false) {
|
public function __construct(Driver $drv, bool $lock = false) {
|
||||||
$this->index = $drv->savepointCreate($lock);
|
$this->index = $drv->savepointCreate($lock);
|
||||||
$this->drv = $drv;
|
$this->drv = $drv;
|
||||||
$this->pending = true;
|
$this->pending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function __destruct() {
|
public function __destruct() {
|
||||||
if ($this->pending) {
|
if ($this->pending) {
|
||||||
try {
|
try {
|
||||||
$this->drv->savepointUndo($this->index);
|
$this->drv->savepointUndo($this->index);
|
||||||
|
@ -23,23 +23,23 @@ class Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function commit(): bool {
|
public function commit(): bool {
|
||||||
$out = $this->drv->savepointRelease($this->index);
|
$out = $this->drv->savepointRelease($this->index);
|
||||||
$this->pending = false;
|
$this->pending = false;
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function rollback(): bool {
|
public function rollback(): bool {
|
||||||
$out = $this->drv->savepointUndo($this->index);
|
$out = $this->drv->savepointUndo($this->index);
|
||||||
$this->pending = false;
|
$this->pending = false;
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIndex(): int {
|
public function getIndex(): int {
|
||||||
return $this->index;
|
return $this->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPending(): bool {
|
public function isPending(): bool {
|
||||||
return $this->pending;
|
return $this->pending;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
use PicoFeed\PicoFeedException;
|
use PicoFeed\PicoFeedException;
|
||||||
use PicoFeed\Config\Config;
|
use PicoFeed\Config\Config;
|
||||||
|
|
12
lib/Lang.php
12
lib/Lang.php
|
@ -16,14 +16,14 @@ class Lang {
|
||||||
];
|
];
|
||||||
|
|
||||||
public $path; // path to locale files; this is a public property to facilitate unit testing
|
public $path; // path to locale files; this is a public property to facilitate unit testing
|
||||||
static protected $requirementsMet = false; // whether the Intl extension is loaded
|
protected static $requirementsMet = false; // whether the Intl extension is loaded
|
||||||
protected $synched = false; // whether the wanted locale is actually loaded (lazy loading is used by default)
|
protected $synched = false; // whether the wanted locale is actually loaded (lazy loading is used by default)
|
||||||
protected $wanted = self::DEFAULT; // the currently requested locale
|
protected $wanted = self::DEFAULT; // the currently requested locale
|
||||||
protected $locale = ""; // the currently loaded locale
|
protected $locale = ""; // the currently loaded locale
|
||||||
protected $loaded = []; // the cascade of loaded locale file names
|
protected $loaded = []; // the cascade of loaded locale file names
|
||||||
protected $strings = self::REQUIRED; // the loaded locale strings, merged
|
protected $strings = self::REQUIRED; // the loaded locale strings, merged
|
||||||
|
|
||||||
function __construct(string $path = BASE."locale".DIRECTORY_SEPARATOR) {
|
public function __construct(string $path = BASE."locale".DIRECTORY_SEPARATOR) {
|
||||||
$this->path = $path;
|
$this->path = $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,13 +73,17 @@ class Lang {
|
||||||
|
|
||||||
public function __invoke(string $msgID, $vars = null): string {
|
public function __invoke(string $msgID, $vars = null): string {
|
||||||
// if we're trying to load the system default language and it fails, we have a chicken and egg problem, so we catch the exception and load no language file instead
|
// if we're trying to load the system default language and it fails, we have a chicken and egg problem, so we catch the exception and load no language file instead
|
||||||
if(!$this->synched) try {$this->load();} catch(Lang\Exception $e) {
|
if (!$this->synched) {
|
||||||
|
try {
|
||||||
|
$this->load();
|
||||||
|
} catch (Lang\Exception $e) {
|
||||||
if ($this->wanted==self::DEFAULT) {
|
if ($this->wanted==self::DEFAULT) {
|
||||||
$this->set("", true);
|
$this->set("", true);
|
||||||
} else {
|
} else {
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// if the requested message is not present in any of the currently loaded language files, throw an exception
|
// if the requested message is not present in any of the currently loaded language files, throw an exception
|
||||||
// note that this is indicative of a programming error since the default locale should have all strings
|
// note that this is indicative of a programming error since the default locale should have all strings
|
||||||
if (!array_key_exists($msgID, $this->strings)) {
|
if (!array_key_exists($msgID, $this->strings)) {
|
||||||
|
@ -117,7 +121,7 @@ class Lang {
|
||||||
return \Locale::lookup($list, $locale, true, $default);
|
return \Locale::lookup($list, $locale, true, $default);
|
||||||
}
|
}
|
||||||
|
|
||||||
static protected function checkRequirements(): bool {
|
protected static function checkRequirements(): bool {
|
||||||
if (!extension_loaded("intl")) {
|
if (!extension_loaded("intl")) {
|
||||||
throw new ExceptionFatal("The \"Intl\" extension is required, but not loaded");
|
throw new ExceptionFatal("The \"Intl\" extension is required, but not loaded");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Misc;
|
namespace JKingWeb\Arsse\Misc;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
|
|
||||||
class Context {
|
class Context {
|
||||||
|
@ -55,68 +56,68 @@ class Context {
|
||||||
return array_values(array_filter($spec));
|
return array_values(array_filter($spec));
|
||||||
}
|
}
|
||||||
|
|
||||||
function reverse(bool $spec = null) {
|
public function reverse(bool $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function limit(int $spec = null) {
|
public function limit(int $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function offset(int $spec = null) {
|
public function offset(int $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function folder(int $spec = null) {
|
public function folder(int $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function subscription(int $spec = null) {
|
public function subscription(int $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function latestEdition(int $spec = null) {
|
public function latestEdition(int $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function oldestEdition(int $spec = null) {
|
public function oldestEdition(int $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function unread(bool $spec = null) {
|
public function unread(bool $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function starred(bool $spec = null) {
|
public function starred(bool $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function modifiedSince($spec = null) {
|
public function modifiedSince($spec = null) {
|
||||||
$spec = Date::normalize($spec);
|
$spec = Date::normalize($spec);
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function notModifiedSince($spec = null) {
|
public function notModifiedSince($spec = null) {
|
||||||
$spec = Date::normalize($spec);
|
$spec = Date::normalize($spec);
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function edition(int $spec = null) {
|
public function edition(int $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function article(int $spec = null) {
|
public function article(int $spec = null) {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function editions(array $spec = null) {
|
public function editions(array $spec = null) {
|
||||||
if ($spec) {
|
if ($spec) {
|
||||||
$spec = $this->cleanArray($spec);
|
$spec = $this->cleanArray($spec);
|
||||||
}
|
}
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function articles(array $spec = null) {
|
public function articles(array $spec = null) {
|
||||||
if ($spec) {
|
if ($spec) {
|
||||||
$spec = $this->cleanArray($spec);
|
$spec = $this->cleanArray($spec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,7 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Misc;
|
namespace JKingWeb\Arsse\Misc;
|
||||||
|
|
||||||
class Date {
|
class Date {
|
||||||
|
public static function transform($date, string $outFormat = null, string $inFormat = null, bool $inLocal = false) {
|
||||||
static function transform($date, string $outFormat = null, string $inFormat = null, bool $inLocal = false) {
|
|
||||||
$date = self::normalize($date, $inFormat, $inLocal);
|
$date = self::normalize($date, $inFormat, $inLocal);
|
||||||
if (is_null($date) || is_null($outFormat)) {
|
if (is_null($date) || is_null($outFormat)) {
|
||||||
return $date;
|
return $date;
|
||||||
|
@ -24,7 +23,7 @@ class Date {
|
||||||
return $date->format($f);
|
return $date->format($f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function normalize($date, string $inFormat = null, bool $inLocal = false) {
|
public static function normalize($date, string $inFormat = null, bool $inLocal = false) {
|
||||||
if ($date instanceof \DateTimeInterface) {
|
if ($date instanceof \DateTimeInterface) {
|
||||||
return $date;
|
return $date;
|
||||||
} elseif (is_numeric($date)) {
|
} elseif (is_numeric($date)) {
|
||||||
|
@ -61,15 +60,15 @@ class Date {
|
||||||
return $d;
|
return $d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function add(string $interval, $date = null): \DateTimeInterface {
|
public static function add(string $interval, $date = null): \DateTimeInterface {
|
||||||
return self::modify("add", $interval, $date);
|
return self::modify("add", $interval, $date);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function sub(string $interval, $date = null): \DateTimeInterface {
|
public static function sub(string $interval, $date = null): \DateTimeInterface {
|
||||||
return self::modify("sub", $interval, $date);
|
return self::modify("sub", $interval, $date);
|
||||||
}
|
}
|
||||||
|
|
||||||
static protected function modify(string $func, string $interval, $date = null): \DateTimeInterface {
|
protected static function modify(string $func, string $interval, $date = null): \DateTimeInterface {
|
||||||
$date = self::normalize($date ?? time());
|
$date = self::normalize($date ?? time());
|
||||||
if ($date instanceof \DateTimeImmutable) {
|
if ($date instanceof \DateTimeImmutable) {
|
||||||
return $date->$func(new \DateInterval($interval));
|
return $date->$func(new \DateInterval($interval));
|
||||||
|
|
|
@ -18,11 +18,11 @@ class Query {
|
||||||
protected $offset = 0;
|
protected $offset = 0;
|
||||||
|
|
||||||
|
|
||||||
function __construct(string $body = "", $types = null, $values = null) {
|
public function __construct(string $body = "", $types = null, $values = null) {
|
||||||
$this->setBody($body, $types, $values);
|
$this->setBody($body, $types, $values);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBody(string $body = "", $types = null, $values = null): bool {
|
public function setBody(string $body = "", $types = null, $values = null): bool {
|
||||||
$this->qBody = $body;
|
$this->qBody = $body;
|
||||||
if (!is_null($types)) {
|
if (!is_null($types)) {
|
||||||
$this->tBody[] = $types;
|
$this->tBody[] = $types;
|
||||||
|
@ -31,7 +31,7 @@ class Query {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCTE(string $tableSpec, string $body, $types = null, $values = null, string $join = ''): bool {
|
public function setCTE(string $tableSpec, string $body, $types = null, $values = null, string $join = ''): bool {
|
||||||
$this->qCTE[] = "$tableSpec as ($body)";
|
$this->qCTE[] = "$tableSpec as ($body)";
|
||||||
if (!is_null($types)) {
|
if (!is_null($types)) {
|
||||||
$this->tCTE[] = $types;
|
$this->tCTE[] = $types;
|
||||||
|
@ -43,7 +43,7 @@ class Query {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWhere(string $where, $types = null, $values = null): bool {
|
public function setWhere(string $where, $types = null, $values = null): bool {
|
||||||
$this->qWhere[] = $where;
|
$this->qWhere[] = $where;
|
||||||
if (!is_null($types)) {
|
if (!is_null($types)) {
|
||||||
$this->tWhere[] = $types;
|
$this->tWhere[] = $types;
|
||||||
|
@ -52,7 +52,7 @@ class Query {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setOrder(string $order, bool $prepend = false): bool {
|
public function setOrder(string $order, bool $prepend = false): bool {
|
||||||
if ($prepend) {
|
if ($prepend) {
|
||||||
array_unshift($this->order, $order);
|
array_unshift($this->order, $order);
|
||||||
} else {
|
} else {
|
||||||
|
@ -61,13 +61,13 @@ class Query {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLimit(int $limit, int $offset = 0): bool {
|
public function setLimit(int $limit, int $offset = 0): bool {
|
||||||
$this->limit = $limit;
|
$this->limit = $limit;
|
||||||
$this->offset = $offset;
|
$this->offset = $offset;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pushCTE(string $tableSpec, string $join = ''): bool {
|
public function pushCTE(string $tableSpec, string $join = ''): bool {
|
||||||
// this function takes the query body and converts it to a common table expression, putting it at the bottom of the existing CTE stack
|
// this function takes the query body and converts it to a common table expression, putting it at the bottom of the existing CTE stack
|
||||||
// all WHERE, ORDER BY, and LIMIT parts belong to the new CTE and are removed from the main query
|
// all WHERE, ORDER BY, and LIMIT parts belong to the new CTE and are removed from the main query
|
||||||
$this->setCTE($tableSpec, $this->buildQueryBody(), [$this->tBody, $this->tWhere], [$this->vBody, $this->vWhere]);
|
$this->setCTE($tableSpec, $this->buildQueryBody(), [$this->tBody, $this->tWhere], [$this->vBody, $this->vWhere]);
|
||||||
|
@ -85,7 +85,7 @@ class Query {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function __toString(): string {
|
public function __toString(): string {
|
||||||
$out = "";
|
$out = "";
|
||||||
if (sizeof($this->qCTE)) {
|
if (sizeof($this->qCTE)) {
|
||||||
// start with common table expressions
|
// start with common table expressions
|
||||||
|
@ -96,31 +96,31 @@ class Query {
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getQuery(): string {
|
public function getQuery(): string {
|
||||||
return $this->__toString();
|
return $this->__toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTypes(): array {
|
public function getTypes(): array {
|
||||||
return [$this->tCTE, $this->tBody, $this->tWhere];
|
return [$this->tCTE, $this->tBody, $this->tWhere];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValues(): array {
|
public function getValues(): array {
|
||||||
return [$this->vCTE, $this->vBody, $this->vWhere];
|
return [$this->vCTE, $this->vBody, $this->vWhere];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWhereTypes(): array {
|
public function getWhereTypes(): array {
|
||||||
return $this->tWhere;
|
return $this->tWhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWhereValues(): array {
|
public function getWhereValues(): array {
|
||||||
return $this->vWhere;
|
return $this->vWhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCTETypes(): array {
|
public function getCTETypes(): array {
|
||||||
return $this->tCTE;
|
return $this->tCTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCTEValues(): array {
|
public function getCTEValues(): array {
|
||||||
return $this->vCTE;
|
return $this->vCTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
lib/REST.php
10
lib/REST.php
|
@ -27,10 +27,10 @@ class REST {
|
||||||
// CommaFeed https://www.commafeed.com/api/
|
// CommaFeed https://www.commafeed.com/api/
|
||||||
];
|
];
|
||||||
|
|
||||||
function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dispatch(REST\Request $req = null): REST\Response {
|
public function dispatch(REST\Request $req = null): REST\Response {
|
||||||
if ($req===null) {
|
if ($req===null) {
|
||||||
$req = new REST\Request();
|
$req = new REST\Request();
|
||||||
}
|
}
|
||||||
|
@ -42,9 +42,11 @@ class REST {
|
||||||
return $drv->dispatch($req);
|
return $drv->dispatch($req);
|
||||||
}
|
}
|
||||||
|
|
||||||
function apiMatch(string $url, array $map): string {
|
public function apiMatch(string $url, array $map): string {
|
||||||
// sort the API list so the longest URL prefixes come first
|
// sort the API list so the longest URL prefixes come first
|
||||||
uasort($map, function($a, $b) {return (strlen($a['match']) <=> strlen($b['match'])) * -1;});
|
uasort($map, function ($a, $b) {
|
||||||
|
return (strlen($a['match']) <=> strlen($b['match'])) * -1;
|
||||||
|
});
|
||||||
// find a match
|
// find a match
|
||||||
foreach ($map as $id => $api) {
|
foreach ($map as $id => $api) {
|
||||||
if (strpos($url, $api['match'])===0) {
|
if (strpos($url, $api['match'])===0) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST;
|
namespace JKingWeb\Arsse\REST;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
|
|
||||||
abstract class AbstractHandler implements Handler {
|
abstract class AbstractHandler implements Handler {
|
||||||
|
abstract public function __construct();
|
||||||
abstract function __construct();
|
abstract public function dispatch(Request $req): Response;
|
||||||
abstract function dispatch(Request $req): Response;
|
|
||||||
|
|
||||||
protected function fieldMapNames(array $data, array $map): array {
|
protected function fieldMapNames(array $data, array $map): array {
|
||||||
$out = [];
|
$out = [];
|
||||||
|
|
|
@ -3,6 +3,6 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST;
|
namespace JKingWeb\Arsse\REST;
|
||||||
|
|
||||||
interface Handler {
|
interface Handler {
|
||||||
function __construct();
|
public function __construct();
|
||||||
function dispatch(Request $req): Response;
|
public function dispatch(Request $req): Response;
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST\NextCloudNews;
|
namespace JKingWeb\Arsse\REST\NextCloudNews;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\User;
|
use JKingWeb\Arsse\User;
|
||||||
use JKingWeb\Arsse\Service;
|
use JKingWeb\Arsse\Service;
|
||||||
|
@ -36,10 +37,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
// 'items' => "array int", // just pass these through
|
// 'items' => "array int", // just pass these through
|
||||||
];
|
];
|
||||||
|
|
||||||
function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dispatch(\JKingWeb\Arsse\REST\Request $req): Response {
|
public function dispatch(\JKingWeb\Arsse\REST\Request $req): Response {
|
||||||
// try to authenticate
|
// try to authenticate
|
||||||
if (!Arsse::$user->authHTTP()) {
|
if (!Arsse::$user->authHTTP()) {
|
||||||
return new Response(401, "", "", ['WWW-Authenticate: Basic realm="'.self::REALM.'"']);
|
return new Response(401, "", "", ['WWW-Authenticate: Basic realm="'.self::REALM.'"']);
|
||||||
|
@ -361,7 +362,8 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
if ($folder) {
|
if ($folder) {
|
||||||
try {
|
try {
|
||||||
Arsse::$db->subscriptionPropertiesSet(Arsse::$user->id, $id, ['folder' => $folder]);
|
Arsse::$db->subscriptionPropertiesSet(Arsse::$user->id, $id, ['folder' => $folder]);
|
||||||
} catch(ExceptionInput $e) {}
|
} catch (ExceptionInput $e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$tr->commit();
|
$tr->commit();
|
||||||
// fetch the feed's metadata and format it appropriately
|
// fetch the feed's metadata and format it appropriately
|
||||||
|
@ -604,7 +606,8 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
$c->editions($in[$a]);
|
$c->editions($in[$a]);
|
||||||
try {
|
try {
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
|
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
|
||||||
} catch(ExceptionInput $e) {}
|
} catch (ExceptionInput $e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$t->commit();
|
$t->commit();
|
||||||
return new Response(204);
|
return new Response(204);
|
||||||
|
@ -627,7 +630,8 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
$c->articles($in[$a]);
|
$c->articles($in[$a]);
|
||||||
try {
|
try {
|
||||||
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
|
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
|
||||||
} catch(ExceptionInput $e) {}
|
} catch (ExceptionInput $e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$t->commit();
|
$t->commit();
|
||||||
return new Response(204);
|
return new Response(204);
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST\NextCloudNews;
|
namespace JKingWeb\Arsse\REST\NextCloudNews;
|
||||||
|
|
||||||
use JKingWeb\Arsse\REST\Response;
|
use JKingWeb\Arsse\REST\Response;
|
||||||
|
|
||||||
class Versions implements \JKingWeb\Arsse\REST\Handler {
|
class Versions implements \JKingWeb\Arsse\REST\Handler {
|
||||||
function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dispatch(\JKingWeb\Arsse\REST\Request $req): Response {
|
public function dispatch(\JKingWeb\Arsse\REST\Request $req): Response {
|
||||||
// if a method other than GET was used, this is an error
|
// if a method other than GET was used, this is an error
|
||||||
if ($req->method != "GET") {
|
if ($req->method != "GET") {
|
||||||
return new Response(405);
|
return new Response(405);
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Request {
|
||||||
public $type ="";
|
public $type ="";
|
||||||
public $body = "";
|
public $body = "";
|
||||||
|
|
||||||
function __construct(string $method = null, string $url = null, string $body = null, string $contentType = null) {
|
public function __construct(string $method = null, string $url = null, string $body = null, string $contentType = null) {
|
||||||
if (is_null($method)) {
|
if (is_null($method)) {
|
||||||
$method = $_SERVER['REQUEST_METHOD'];
|
$method = $_SERVER['REQUEST_METHOD'];
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,9 @@ class Request {
|
||||||
array_pop($paths);
|
array_pop($paths);
|
||||||
}
|
}
|
||||||
// %-decode each path element
|
// %-decode each path element
|
||||||
$paths = array_map(function($v){return rawurldecode($v);}, $paths);
|
$paths = array_map(function ($v) {
|
||||||
|
return rawurldecode($v);
|
||||||
|
}, $paths);
|
||||||
$out['paths'] = $paths;
|
$out['paths'] = $paths;
|
||||||
}
|
}
|
||||||
return $out;
|
return $out;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST;
|
namespace JKingWeb\Arsse\REST;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
|
|
||||||
class Response {
|
class Response {
|
||||||
|
@ -14,14 +15,14 @@ class Response {
|
||||||
public $fields;
|
public $fields;
|
||||||
|
|
||||||
|
|
||||||
function __construct(int $code, $payload = null, string $type = self::T_JSON, array $extraFields = []) {
|
public function __construct(int $code, $payload = null, string $type = self::T_JSON, array $extraFields = []) {
|
||||||
$this->code = $code;
|
$this->code = $code;
|
||||||
$this->payload = $payload;
|
$this->payload = $payload;
|
||||||
$this->type = $type;
|
$this->type = $type;
|
||||||
$this->fields = $extraFields;
|
$this->fields = $extraFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
function output() {
|
public function output() {
|
||||||
if (!headers_sent()) {
|
if (!headers_sent()) {
|
||||||
try {
|
try {
|
||||||
$statusText = Arsse::$lang->msg("HTTP.Status.".$this->code);
|
$statusText = Arsse::$lang->msg("HTTP.Status.".$this->code);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
|
|
||||||
class Service {
|
class Service {
|
||||||
|
@ -10,7 +11,7 @@ class Service {
|
||||||
/** @var \DateInterval */
|
/** @var \DateInterval */
|
||||||
protected $interval;
|
protected $interval;
|
||||||
|
|
||||||
static public function driverList(): array {
|
public static function driverList(): array {
|
||||||
$sep = \DIRECTORY_SEPARATOR;
|
$sep = \DIRECTORY_SEPARATOR;
|
||||||
$path = __DIR__.$sep."Service".$sep;
|
$path = __DIR__.$sep."Service".$sep;
|
||||||
$classes = [];
|
$classes = [];
|
||||||
|
@ -30,13 +31,13 @@ class Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function __construct() {
|
public function __construct() {
|
||||||
$driver = Arsse::$conf->serviceDriver;
|
$driver = Arsse::$conf->serviceDriver;
|
||||||
$this->drv = new $driver();
|
$this->drv = new $driver();
|
||||||
$this->interval = static::interval();
|
$this->interval = static::interval();
|
||||||
}
|
}
|
||||||
|
|
||||||
function watch(bool $loop = true): \DateTimeInterface {
|
public function watch(bool $loop = true): \DateTimeInterface {
|
||||||
$t = new \DateTime();
|
$t = new \DateTime();
|
||||||
do {
|
do {
|
||||||
$this->checkIn();
|
$this->checkIn();
|
||||||
|
@ -59,11 +60,11 @@ class Service {
|
||||||
return $t;
|
return $t;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIn(): bool {
|
public function checkIn(): bool {
|
||||||
return Arsse::$db->metaSet("service_last_checkin", time(), "datetime");
|
return Arsse::$db->metaSet("service_last_checkin", time(), "datetime");
|
||||||
}
|
}
|
||||||
|
|
||||||
static function hasCheckedIn(): bool {
|
public static function hasCheckedIn(): bool {
|
||||||
$checkin = Arsse::$db->metaGet("service_last_checkin");
|
$checkin = Arsse::$db->metaGet("service_last_checkin");
|
||||||
// if the service has never checked in, return false
|
// if the service has never checked in, return false
|
||||||
if (!$checkin) {
|
if (!$checkin) {
|
||||||
|
@ -81,12 +82,12 @@ class Service {
|
||||||
return ($checkin >= $limit);
|
return ($checkin >= $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function cleanupPre(): bool {
|
public static function cleanupPre(): bool {
|
||||||
// mark unsubscribed feeds as orphaned and delete orphaned feeds that are beyond their retention period
|
// mark unsubscribed feeds as orphaned and delete orphaned feeds that are beyond their retention period
|
||||||
return Arsse::$db->feedCleanup();
|
return Arsse::$db->feedCleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
static function cleanupPost(): bool {
|
public static function cleanupPost(): bool {
|
||||||
// delete old articles, according to configured threasholds
|
// delete old articles, according to configured threasholds
|
||||||
return Arsse::$db->articleCleanup();
|
return Arsse::$db->articleCleanup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Service\Curl;
|
namespace JKingWeb\Arsse\Service\Curl;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
|
|
||||||
class Driver implements \JKingWeb\Arsse\Service\Driver {
|
class Driver implements \JKingWeb\Arsse\Service\Driver {
|
||||||
|
@ -8,15 +9,15 @@ class Driver implements \JKingWeb\Arsse\Service\Driver {
|
||||||
protected $queue;
|
protected $queue;
|
||||||
protected $handles = [];
|
protected $handles = [];
|
||||||
|
|
||||||
static function driverName(): string {
|
public static function driverName(): string {
|
||||||
return Arsse::$lang->msg("Driver.Service.Curl.Name");
|
return Arsse::$lang->msg("Driver.Service.Curl.Name");
|
||||||
}
|
}
|
||||||
|
|
||||||
static function requirementsMet(): bool {
|
public static function requirementsMet(): bool {
|
||||||
return extension_loaded("curl");
|
return extension_loaded("curl");
|
||||||
}
|
}
|
||||||
|
|
||||||
function __construct() {
|
public function __construct() {
|
||||||
//default curl options for individual requests
|
//default curl options for individual requests
|
||||||
$this->options = [
|
$this->options = [
|
||||||
\CURLOPT_URL => Arsse::$serviceCurlBase."index.php/apps/news/api/v1-2/feeds/update",
|
\CURLOPT_URL => Arsse::$serviceCurlBase."index.php/apps/news/api/v1-2/feeds/update",
|
||||||
|
@ -42,7 +43,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver {
|
||||||
curl_multi_setopt($this->queue, \CURLMOPT_PIPELINING, 1);
|
curl_multi_setopt($this->queue, \CURLMOPT_PIPELINING, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function queue(int ...$feeds): int {
|
public function queue(int ...$feeds): int {
|
||||||
foreach ($feeds as $id) {
|
foreach ($feeds as $id) {
|
||||||
$h = curl_init();
|
$h = curl_init();
|
||||||
curl_setopt($h, \CURLOPT_POSTFIELDS, json_encode(['userId' => "", 'feedId' => $id]));
|
curl_setopt($h, \CURLOPT_POSTFIELDS, json_encode(['userId' => "", 'feedId' => $id]));
|
||||||
|
@ -52,7 +53,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver {
|
||||||
return sizeof($this->handles);
|
return sizeof($this->handles);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exec(): int {
|
public function exec(): int {
|
||||||
$active = 0;
|
$active = 0;
|
||||||
do {
|
do {
|
||||||
curl_multi_exec($this->queue, $active);
|
curl_multi_exec($this->queue, $active);
|
||||||
|
@ -61,7 +62,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver {
|
||||||
return Arsse::$conf->serviceQueueWidth - $active;
|
return Arsse::$conf->serviceQueueWidth - $active;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clean(): bool {
|
public function clean(): bool {
|
||||||
foreach ($this->handles as $h) {
|
foreach ($this->handles as $h) {
|
||||||
curl_multi_remove_handle($this->queue, $h);
|
curl_multi_remove_handle($this->queue, $h);
|
||||||
curl_close($h);
|
curl_close($h);
|
||||||
|
|
|
@ -3,9 +3,9 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Service;
|
namespace JKingWeb\Arsse\Service;
|
||||||
|
|
||||||
interface Driver {
|
interface Driver {
|
||||||
static function driverName(): string;
|
public static function driverName(): string;
|
||||||
static function requirementsMet(): bool;
|
public static function requirementsMet(): bool;
|
||||||
function queue(int ...$feeds): int;
|
public function queue(int ...$feeds): int;
|
||||||
function exec(): int;
|
public function exec(): int;
|
||||||
function clean(): bool;
|
public function clean(): bool;
|
||||||
}
|
}
|
|
@ -1,28 +1,29 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Service\Forking;
|
namespace JKingWeb\Arsse\Service\Forking;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
|
|
||||||
class Driver implements \JKingWeb\Arsse\Service\Driver {
|
class Driver implements \JKingWeb\Arsse\Service\Driver {
|
||||||
protected $queue = [];
|
protected $queue = [];
|
||||||
|
|
||||||
static function driverName(): string {
|
public static function driverName(): string {
|
||||||
return Arsse::$lang->msg("Driver.Service.Forking.Name");
|
return Arsse::$lang->msg("Driver.Service.Forking.Name");
|
||||||
}
|
}
|
||||||
|
|
||||||
static function requirementsMet(): bool {
|
public static function requirementsMet(): bool {
|
||||||
return function_exists("popen");
|
return function_exists("popen");
|
||||||
}
|
}
|
||||||
|
|
||||||
function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function queue(int ...$feeds): int {
|
public function queue(int ...$feeds): int {
|
||||||
$this->queue = array_merge($this->queue, $feeds);
|
$this->queue = array_merge($this->queue, $feeds);
|
||||||
return sizeof($this->queue);
|
return sizeof($this->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exec(): int {
|
public function exec(): int {
|
||||||
$pp = [];
|
$pp = [];
|
||||||
while ($this->queue) {
|
while ($this->queue) {
|
||||||
$id = (int) array_shift($this->queue);
|
$id = (int) array_shift($this->queue);
|
||||||
|
@ -38,7 +39,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver {
|
||||||
return Arsse::$conf->serviceQueueWidth - sizeof($this->queue);
|
return Arsse::$conf->serviceQueueWidth - sizeof($this->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function clean(): bool {
|
public function clean(): bool {
|
||||||
$this->queue = [];
|
$this->queue = [];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,30 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Service\Internal;
|
namespace JKingWeb\Arsse\Service\Internal;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
|
|
||||||
class Driver implements \JKingWeb\Arsse\Service\Driver {
|
class Driver implements \JKingWeb\Arsse\Service\Driver {
|
||||||
protected $queue = [];
|
protected $queue = [];
|
||||||
|
|
||||||
static function driverName(): string {
|
public static function driverName(): string {
|
||||||
return Arsse::$lang->msg("Driver.Service.Internal.Name");
|
return Arsse::$lang->msg("Driver.Service.Internal.Name");
|
||||||
}
|
}
|
||||||
|
|
||||||
static function requirementsMet(): bool {
|
public static function requirementsMet(): bool {
|
||||||
// this driver has no requirements
|
// this driver has no requirements
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function queue(int ...$feeds): int {
|
public function queue(int ...$feeds): int {
|
||||||
$this->queue = array_merge($this->queue, $feeds);
|
$this->queue = array_merge($this->queue, $feeds);
|
||||||
return sizeof($this->queue);
|
return sizeof($this->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exec(): int {
|
public function exec(): int {
|
||||||
while (sizeof($this->queue)) {
|
while (sizeof($this->queue)) {
|
||||||
$id = array_shift($this->queue);
|
$id = array_shift($this->queue);
|
||||||
Arsse::$db->feedUpdate($id);
|
Arsse::$db->feedUpdate($id);
|
||||||
|
@ -31,7 +32,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver {
|
||||||
return Arsse::$conf->serviceQueueWidth - sizeof($this->queue);
|
return Arsse::$conf->serviceQueueWidth - sizeof($this->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function clean(): bool {
|
public function clean(): bool {
|
||||||
$this->queue = [];
|
$this->queue = [];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ class User {
|
||||||
protected $authzSupported = 0;
|
protected $authzSupported = 0;
|
||||||
protected $actor = [];
|
protected $actor = [];
|
||||||
|
|
||||||
static public function driverList(): array {
|
public static function driverList(): array {
|
||||||
$sep = \DIRECTORY_SEPARATOR;
|
$sep = \DIRECTORY_SEPARATOR;
|
||||||
$path = __DIR__.$sep."User".$sep;
|
$path = __DIR__.$sep."User".$sep;
|
||||||
$classes = [];
|
$classes = [];
|
||||||
|
@ -44,7 +44,7 @@ class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks whether the logged in user is authorized to act for the affected user (used especially when granting rights)
|
// checks whether the logged in user is authorized to act for the affected user (used especially when granting rights)
|
||||||
function authorize(string $affectedUser, string $action, int $newRightsLevel = 0): bool {
|
public function authorize(string $affectedUser, string $action, int $newRightsLevel = 0): bool {
|
||||||
// if authorization checks are disabled (either because we're running the installer or the background updater) just return true
|
// if authorization checks are disabled (either because we're running the installer or the background updater) just return true
|
||||||
if (!$this->authorizationEnabled()) {
|
if (!$this->authorizationEnabled()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -435,7 +435,8 @@ class User {
|
||||||
if ($this->u->driverFunctions("userPropertiesGet")==User\Driver::FUNC_EXTERNAL) {
|
if ($this->u->driverFunctions("userPropertiesGet")==User\Driver::FUNC_EXTERNAL) {
|
||||||
Arsse::$db->userPropertiesSet($user, $this->u->userPropertiesGet($user));
|
Arsse::$db->userPropertiesSet($user, $this->u->userPropertiesGet($user));
|
||||||
}
|
}
|
||||||
} catch(\Throwable $e) {}
|
} catch (\Throwable $e) {
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// otherwise if values are provided, use those
|
// otherwise if values are provided, use those
|
||||||
Arsse::$db->userPropertiesSet($user, $properties);
|
Arsse::$db->userPropertiesSet($user, $properties);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\User;
|
namespace JKingWeb\Arsse\User;
|
||||||
|
|
||||||
Interface Driver {
|
interface Driver {
|
||||||
const FUNC_NOT_IMPLEMENTED = 0;
|
const FUNC_NOT_IMPLEMENTED = 0;
|
||||||
const FUNC_INTERNAL = 1;
|
const FUNC_INTERNAL = 1;
|
||||||
const FUNC_EXTERNAL = 2;
|
const FUNC_EXTERNAL = 2;
|
||||||
|
@ -14,29 +14,29 @@ Interface Driver {
|
||||||
const RIGHTS_GLOBAL_ADMIN = 100; // is completely unrestricted
|
const RIGHTS_GLOBAL_ADMIN = 100; // is completely unrestricted
|
||||||
|
|
||||||
// returns an instance of a class implementing this interface.
|
// returns an instance of a class implementing this interface.
|
||||||
function __construct();
|
public function __construct();
|
||||||
// returns a human-friendly name for the driver (for display in installer, for example)
|
// returns a human-friendly name for the driver (for display in installer, for example)
|
||||||
static function driverName(): string;
|
public static function driverName(): string;
|
||||||
// returns an array (or single queried member of same) of methods defined by this interface and whether the class implements the internal function or a custom version
|
// returns an array (or single queried member of same) of methods defined by this interface and whether the class implements the internal function or a custom version
|
||||||
function driverFunctions(string $function = null);
|
public function driverFunctions(string $function = null);
|
||||||
// authenticates a user against their name and password
|
// authenticates a user against their name and password
|
||||||
function auth(string $user, string $password): bool;
|
public function auth(string $user, string $password): bool;
|
||||||
// checks whether a user exists
|
// checks whether a user exists
|
||||||
function userExists(string $user): bool;
|
public function userExists(string $user): bool;
|
||||||
// adds a user
|
// adds a user
|
||||||
function userAdd(string $user, string $password = null): string;
|
public function userAdd(string $user, string $password = null): string;
|
||||||
// removes a user
|
// removes a user
|
||||||
function userRemove(string $user): bool;
|
public function userRemove(string $user): bool;
|
||||||
// lists all users
|
// lists all users
|
||||||
function userList(string $domain = null): array;
|
public function userList(string $domain = null): array;
|
||||||
// sets a user's password; if the driver does not require the old password, it may be ignored
|
// sets a user's password; if the driver does not require the old password, it may be ignored
|
||||||
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string;
|
public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string;
|
||||||
// gets user metadata (currently not useful)
|
// gets user metadata (currently not useful)
|
||||||
function userPropertiesGet(string $user): array;
|
public function userPropertiesGet(string $user): array;
|
||||||
// sets user metadata (currently not useful)
|
// sets user metadata (currently not useful)
|
||||||
function userPropertiesSet(string $user, array $properties): array;
|
public function userPropertiesSet(string $user, array $properties): array;
|
||||||
// returns a user's access level according to RIGHTS_* constants (or some custom semantics, if using custom implementation of authorize())
|
// returns a user's access level according to RIGHTS_* constants (or some custom semantics, if using custom implementation of authorize())
|
||||||
function userRightsGet(string $user): int;
|
public function userRightsGet(string $user): int;
|
||||||
// sets a user's access level
|
// sets a user's access level
|
||||||
function userRightsSet(string $user, int $level): bool;
|
public function userRightsSet(string $user, int $level): bool;
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@ final class Driver implements \JKingWeb\Arsse\User\Driver {
|
||||||
"userRightsSet" => self::FUNC_INTERNAL,
|
"userRightsSet" => self::FUNC_INTERNAL,
|
||||||
];
|
];
|
||||||
|
|
||||||
static public function driverName(): string {
|
public static function driverName(): string {
|
||||||
return Arsse::$lang->msg("Driver.User.Internal.Name");
|
return Arsse::$lang->msg("Driver.User.Internal.Name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\User\Internal;
|
namespace JKingWeb\Arsse\User\Internal;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\User\Exception;
|
use JKingWeb\Arsse\User\Exception;
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ trait InternalFunctions {
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function auth(string $user, string $password): bool {
|
public function auth(string $user, string $password): bool {
|
||||||
try {
|
try {
|
||||||
$hash = Arsse::$db->userPasswordGet($user);
|
$hash = Arsse::$db->userPasswordGet($user);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
@ -22,39 +23,39 @@ trait InternalFunctions {
|
||||||
return password_verify($password, $hash);
|
return password_verify($password, $hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userExists(string $user): bool {
|
public function userExists(string $user): bool {
|
||||||
return Arsse::$db->userExists($user);
|
return Arsse::$db->userExists($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userAdd(string $user, string $password = null): string {
|
public function userAdd(string $user, string $password = null): string {
|
||||||
return Arsse::$db->userAdd($user, $password);
|
return Arsse::$db->userAdd($user, $password);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRemove(string $user): bool {
|
public function userRemove(string $user): bool {
|
||||||
return Arsse::$db->userRemove($user);
|
return Arsse::$db->userRemove($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userList(string $domain = null): array {
|
public function userList(string $domain = null): array {
|
||||||
return Arsse::$db->userList($domain);
|
return Arsse::$db->userList($domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
||||||
return Arsse::$db->userPasswordSet($user, $newPassword);
|
return Arsse::$db->userPasswordSet($user, $newPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPropertiesGet(string $user): array {
|
public function userPropertiesGet(string $user): array {
|
||||||
return Arsse::$db->userPropertiesGet($user);
|
return Arsse::$db->userPropertiesGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPropertiesSet(string $user, array $properties): array {
|
public function userPropertiesSet(string $user, array $properties): array {
|
||||||
return Arsse::$db->userPropertiesSet($user, $properties);
|
return Arsse::$db->userPropertiesSet($user, $properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsGet(string $user): int {
|
public function userRightsGet(string $user): int {
|
||||||
return Arsse::$db->userRightsGet($user);
|
return Arsse::$db->userRightsGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsSet(string $user, int $level): bool {
|
public function userRightsSet(string $user, int $level): bool {
|
||||||
return Arsse::$db->userRightsSet($user, $level);
|
return Arsse::$db->userRightsSet($user, $level);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use org\bovigo\vfs\vfsStream;
|
use org\bovigo\vfs\vfsStream;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\Conf */
|
/** @covers \JKingWeb\Arsse\Conf */
|
||||||
class TestConf extends Test\AbstractTest {
|
class TestConf extends Test\AbstractTest {
|
||||||
static $vfs;
|
public static $vfs;
|
||||||
static $path;
|
public static $path;
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
self::$vfs = vfsStream::setup("root", null, [
|
self::$vfs = vfsStream::setup("root", null, [
|
||||||
'confGood' => '<?php return Array("lang" => "xx");',
|
'confGood' => '<?php return Array("lang" => "xx");',
|
||||||
|
@ -26,18 +27,18 @@ class TestConf extends Test\AbstractTest {
|
||||||
chmod(self::$path."confForbidden", 0000);
|
chmod(self::$path."confForbidden", 0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
self::$path = null;
|
self::$path = null;
|
||||||
self::$vfs = null;
|
self::$vfs = null;
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadDefaultValues() {
|
public function testLoadDefaultValues() {
|
||||||
$this->assertInstanceOf(Conf::class, new Conf());
|
$this->assertInstanceOf(Conf::class, new Conf());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @depends testLoadDefaultValues */
|
/** @depends testLoadDefaultValues */
|
||||||
function testImportFromArray() {
|
public function testImportFromArray() {
|
||||||
$arr = ['lang' => "xx"];
|
$arr = ['lang' => "xx"];
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->import($arr);
|
$conf->import($arr);
|
||||||
|
@ -45,7 +46,7 @@ class TestConf extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @depends testImportFromArray */
|
/** @depends testImportFromArray */
|
||||||
function testImportFromFile() {
|
public function testImportFromFile() {
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->importFile(self::$path."confGood");
|
$conf->importFile(self::$path."confGood");
|
||||||
$this->assertEquals("xx", $conf->lang);
|
$this->assertEquals("xx", $conf->lang);
|
||||||
|
@ -54,43 +55,43 @@ class TestConf extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @depends testImportFromFile */
|
/** @depends testImportFromFile */
|
||||||
function testImportFromMissingFile() {
|
public function testImportFromMissingFile() {
|
||||||
$this->assertException("fileMissing", "Conf");
|
$this->assertException("fileMissing", "Conf");
|
||||||
$conf = new Conf(self::$path."confMissing");
|
$conf = new Conf(self::$path."confMissing");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @depends testImportFromFile */
|
/** @depends testImportFromFile */
|
||||||
function testImportFromEmptyFile() {
|
public function testImportFromEmptyFile() {
|
||||||
$this->assertException("fileCorrupt", "Conf");
|
$this->assertException("fileCorrupt", "Conf");
|
||||||
$conf = new Conf(self::$path."confEmpty");
|
$conf = new Conf(self::$path."confEmpty");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @depends testImportFromFile */
|
/** @depends testImportFromFile */
|
||||||
function testImportFromFileWithoutReadPermission() {
|
public function testImportFromFileWithoutReadPermission() {
|
||||||
$this->assertException("fileUnreadable", "Conf");
|
$this->assertException("fileUnreadable", "Conf");
|
||||||
$conf = new Conf(self::$path."confUnreadable");
|
$conf = new Conf(self::$path."confUnreadable");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @depends testImportFromFile */
|
/** @depends testImportFromFile */
|
||||||
function testImportFromFileWhichIsNotAnArray() {
|
public function testImportFromFileWhichIsNotAnArray() {
|
||||||
$this->assertException("fileCorrupt", "Conf");
|
$this->assertException("fileCorrupt", "Conf");
|
||||||
$conf = new Conf(self::$path."confNotArray");
|
$conf = new Conf(self::$path."confNotArray");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @depends testImportFromFile */
|
/** @depends testImportFromFile */
|
||||||
function testImportFromFileWhichIsNotPhp() {
|
public function testImportFromFileWhichIsNotPhp() {
|
||||||
$this->assertException("fileCorrupt", "Conf");
|
$this->assertException("fileCorrupt", "Conf");
|
||||||
// this should not print the output of the non-PHP file
|
// this should not print the output of the non-PHP file
|
||||||
$conf = new Conf(self::$path."confNotPHP");
|
$conf = new Conf(self::$path."confNotPHP");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @depends testImportFromFile */
|
/** @depends testImportFromFile */
|
||||||
function testImportFromCorruptFile() {
|
public function testImportFromCorruptFile() {
|
||||||
$this->assertException("fileCorrupt", "Conf");
|
$this->assertException("fileCorrupt", "Conf");
|
||||||
$conf = new Conf(self::$path."confCorrupt");
|
$conf = new Conf(self::$path."confCorrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExportToArray() {
|
public function testExportToArray() {
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->lang = ["en", "fr"]; // should not be exported: not scalar
|
$conf->lang = ["en", "fr"]; // should not be exported: not scalar
|
||||||
$conf->dbSQLite3File = "test.db"; // should be exported: value changed
|
$conf->dbSQLite3File = "test.db"; // should be exported: value changed
|
||||||
|
@ -107,7 +108,7 @@ class TestConf extends Test\AbstractTest {
|
||||||
|
|
||||||
/** @depends testExportToArray
|
/** @depends testExportToArray
|
||||||
* @depends testImportFromFile */
|
* @depends testImportFromFile */
|
||||||
function testExportToFile() {
|
public function testExportToFile() {
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->lang = ["en", "fr"]; // should not be exported: not scalar
|
$conf->lang = ["en", "fr"]; // should not be exported: not scalar
|
||||||
$conf->dbSQLite3File = "test.db"; // should be exported: value changed
|
$conf->dbSQLite3File = "test.db"; // should be exported: value changed
|
||||||
|
@ -125,12 +126,12 @@ class TestConf extends Test\AbstractTest {
|
||||||
$this->assertArraySubset($exp, $arr);
|
$this->assertArraySubset($exp, $arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExportToFileWithoutWritePermission() {
|
public function testExportToFileWithoutWritePermission() {
|
||||||
$this->assertException("fileUnwritable", "Conf");
|
$this->assertException("fileUnwritable", "Conf");
|
||||||
(new Conf)->exportFile(self::$path."confUnreadable");
|
(new Conf)->exportFile(self::$path."confUnreadable");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExportToFileWithoutCreatePermission() {
|
public function testExportToFileWithoutCreatePermission() {
|
||||||
$this->assertException("fileUncreatable", "Conf");
|
$this->assertException("fileUncreatable", "Conf");
|
||||||
(new Conf)->exportFile(self::$path."confForbidden/conf");
|
(new Conf)->exportFile(self::$path."confForbidden/conf");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use org\bovigo\vfs\vfsStream;
|
use org\bovigo\vfs\vfsStream;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
@ -13,7 +14,7 @@ class TestDbDriverCreationSQLite3 extends Test\AbstractTest {
|
||||||
protected $drv;
|
protected $drv;
|
||||||
protected $ch;
|
protected $ch;
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
if (!extension_loaded("sqlite3")) {
|
if (!extension_loaded("sqlite3")) {
|
||||||
$this->markTestSkipped("SQLite extension not loaded");
|
$this->markTestSkipped("SQLite extension not loaded");
|
||||||
}
|
}
|
||||||
|
@ -105,83 +106,83 @@ class TestDbDriverCreationSQLite3 extends Test\AbstractTest {
|
||||||
// set up database shim
|
// set up database shim
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToCreateDatabase() {
|
public function testFailToCreateDatabase() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Cmain/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Cmain/arsse.db";
|
||||||
$this->assertException("fileUncreatable", "Db");
|
$this->assertException("fileUncreatable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToCreateJournal() {
|
public function testFailToCreateJournal() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Cwal/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Cwal/arsse.db";
|
||||||
$this->assertException("fileUncreatable", "Db");
|
$this->assertException("fileUncreatable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToCreateSharedMmeory() {
|
public function testFailToCreateSharedMmeory() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Cshm/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Cshm/arsse.db";
|
||||||
$this->assertException("fileUncreatable", "Db");
|
$this->assertException("fileUncreatable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToReadDatabase() {
|
public function testFailToReadDatabase() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Rmain/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Rmain/arsse.db";
|
||||||
$this->assertException("fileUnreadable", "Db");
|
$this->assertException("fileUnreadable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToReadJournal() {
|
public function testFailToReadJournal() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Rwal/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Rwal/arsse.db";
|
||||||
$this->assertException("fileUnreadable", "Db");
|
$this->assertException("fileUnreadable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToReadSharedMmeory() {
|
public function testFailToReadSharedMmeory() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Rshm/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Rshm/arsse.db";
|
||||||
$this->assertException("fileUnreadable", "Db");
|
$this->assertException("fileUnreadable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToWriteToDatabase() {
|
public function testFailToWriteToDatabase() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Wmain/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Wmain/arsse.db";
|
||||||
$this->assertException("fileUnwritable", "Db");
|
$this->assertException("fileUnwritable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToWriteToJournal() {
|
public function testFailToWriteToJournal() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Wwal/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Wwal/arsse.db";
|
||||||
$this->assertException("fileUnwritable", "Db");
|
$this->assertException("fileUnwritable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToWriteToSharedMmeory() {
|
public function testFailToWriteToSharedMmeory() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Wshm/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Wshm/arsse.db";
|
||||||
$this->assertException("fileUnwritable", "Db");
|
$this->assertException("fileUnwritable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToAccessDatabase() {
|
public function testFailToAccessDatabase() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Amain/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Amain/arsse.db";
|
||||||
$this->assertException("fileUnusable", "Db");
|
$this->assertException("fileUnusable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToAccessJournal() {
|
public function testFailToAccessJournal() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Awal/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Awal/arsse.db";
|
||||||
$this->assertException("fileUnusable", "Db");
|
$this->assertException("fileUnusable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFailToAccessSharedMmeory() {
|
public function testFailToAccessSharedMmeory() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."Ashm/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."Ashm/arsse.db";
|
||||||
$this->assertException("fileUnusable", "Db");
|
$this->assertException("fileUnusable", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAssumeDatabaseCorruption() {
|
public function testAssumeDatabaseCorruption() {
|
||||||
Arsse::$conf->dbSQLite3File = $this->path."corrupt/arsse.db";
|
Arsse::$conf->dbSQLite3File = $this->path."corrupt/arsse.db";
|
||||||
$this->assertException("fileCorrupt", "Db");
|
$this->assertException("fileCorrupt", "Db");
|
||||||
new Db\SQLite3\Driver;
|
new Db\SQLite3\Driver;
|
||||||
|
|
|
@ -10,7 +10,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
protected $drv;
|
protected $drv;
|
||||||
protected $ch;
|
protected $ch;
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
if (!extension_loaded("sqlite3")) {
|
if (!extension_loaded("sqlite3")) {
|
||||||
$this->markTestSkipped("SQLite extension not loaded");
|
$this->markTestSkipped("SQLite extension not loaded");
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->ch->enableExceptions(true);
|
$this->ch->enableExceptions(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
unset($this->drv);
|
unset($this->drv);
|
||||||
unset($this->ch);
|
unset($this->ch);
|
||||||
if (isset(Arsse::$conf)) {
|
if (isset(Arsse::$conf)) {
|
||||||
|
@ -33,101 +33,101 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchDriverName() {
|
public function testFetchDriverName() {
|
||||||
$class = Arsse::$conf->dbDriver;
|
$class = Arsse::$conf->dbDriver;
|
||||||
$this->assertTrue(strlen($class::driverName()) > 0);
|
$this->assertTrue(strlen($class::driverName()) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExecAValidStatement() {
|
public function testExecAValidStatement() {
|
||||||
$this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key)"));
|
$this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExecAnInvalidStatement() {
|
public function testExecAnInvalidStatement() {
|
||||||
$this->assertException("engineErrorGeneral", "Db");
|
$this->assertException("engineErrorGeneral", "Db");
|
||||||
$this->drv->exec("And the meek shall inherit the earth...");
|
$this->drv->exec("And the meek shall inherit the earth...");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExecMultipleStatements() {
|
public function testExecMultipleStatements() {
|
||||||
$this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key); INSERT INTO test(id) values(2112)"));
|
$this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key); INSERT INTO test(id) values(2112)"));
|
||||||
$this->assertEquals(2112, $this->ch->querySingle("SELECT id from test"));
|
$this->assertEquals(2112, $this->ch->querySingle("SELECT id from test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExecTimeout() {
|
public function testExecTimeout() {
|
||||||
$this->ch->exec("BEGIN EXCLUSIVE TRANSACTION");
|
$this->ch->exec("BEGIN EXCLUSIVE TRANSACTION");
|
||||||
$this->assertException("general", "Db", "ExceptionTimeout");
|
$this->assertException("general", "Db", "ExceptionTimeout");
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExecConstraintViolation() {
|
public function testExecConstraintViolation() {
|
||||||
$this->drv->exec("CREATE TABLE test(id integer not null)");
|
$this->drv->exec("CREATE TABLE test(id integer not null)");
|
||||||
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
||||||
$this->drv->exec("INSERT INTO test(id) values(null)");
|
$this->drv->exec("INSERT INTO test(id) values(null)");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExecTypeViolation() {
|
public function testExecTypeViolation() {
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
||||||
$this->drv->exec("INSERT INTO test(id) values('ook')");
|
$this->drv->exec("INSERT INTO test(id) values('ook')");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMakeAValidQuery() {
|
public function testMakeAValidQuery() {
|
||||||
$this->assertInstanceOf(Db\Result::class, $this->drv->query("SELECT 1"));
|
$this->assertInstanceOf(Db\Result::class, $this->drv->query("SELECT 1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMakeAnInvalidQuery() {
|
public function testMakeAnInvalidQuery() {
|
||||||
$this->assertException("engineErrorGeneral", "Db");
|
$this->assertException("engineErrorGeneral", "Db");
|
||||||
$this->drv->query("Apollo was astonished; Dionysus thought me mad");
|
$this->drv->query("Apollo was astonished; Dionysus thought me mad");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testQueryTimeout() {
|
public function testQueryTimeout() {
|
||||||
$this->ch->exec("BEGIN EXCLUSIVE TRANSACTION");
|
$this->ch->exec("BEGIN EXCLUSIVE TRANSACTION");
|
||||||
$this->assertException("general", "Db", "ExceptionTimeout");
|
$this->assertException("general", "Db", "ExceptionTimeout");
|
||||||
$this->drv->query("CREATE TABLE test(id integer primary key)");
|
$this->drv->query("CREATE TABLE test(id integer primary key)");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testQueryConstraintViolation() {
|
public function testQueryConstraintViolation() {
|
||||||
$this->drv->exec("CREATE TABLE test(id integer not null)");
|
$this->drv->exec("CREATE TABLE test(id integer not null)");
|
||||||
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
||||||
$this->drv->query("INSERT INTO test(id) values(null)");
|
$this->drv->query("INSERT INTO test(id) values(null)");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testQueryTypeViolation() {
|
public function testQueryTypeViolation() {
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
||||||
$this->drv->query("INSERT INTO test(id) values('ook')");
|
$this->drv->query("INSERT INTO test(id) values('ook')");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPrepareAValidQuery() {
|
public function testPrepareAValidQuery() {
|
||||||
$s = $this->drv->prepare("SELECT ?, ?", "int", "int");
|
$s = $this->drv->prepare("SELECT ?, ?", "int", "int");
|
||||||
$this->assertInstanceOf(Db\Statement::class, $s);
|
$this->assertInstanceOf(Db\Statement::class, $s);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPrepareAnInvalidQuery() {
|
public function testPrepareAnInvalidQuery() {
|
||||||
$this->assertException("engineErrorGeneral", "Db");
|
$this->assertException("engineErrorGeneral", "Db");
|
||||||
$s = $this->drv->prepare("This is an invalid query", "int", "int");
|
$s = $this->drv->prepare("This is an invalid query", "int", "int");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCreateASavepoint() {
|
public function testCreateASavepoint() {
|
||||||
$this->assertEquals(1, $this->drv->savepointCreate());
|
$this->assertEquals(1, $this->drv->savepointCreate());
|
||||||
$this->assertEquals(2, $this->drv->savepointCreate());
|
$this->assertEquals(2, $this->drv->savepointCreate());
|
||||||
$this->assertEquals(3, $this->drv->savepointCreate());
|
$this->assertEquals(3, $this->drv->savepointCreate());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testReleaseASavepoint() {
|
public function testReleaseASavepoint() {
|
||||||
$this->assertEquals(1, $this->drv->savepointCreate());
|
$this->assertEquals(1, $this->drv->savepointCreate());
|
||||||
$this->assertEquals(true, $this->drv->savepointRelease());
|
$this->assertEquals(true, $this->drv->savepointRelease());
|
||||||
$this->assertException("invalid", "Db", "ExceptionSavepoint");
|
$this->assertException("invalid", "Db", "ExceptionSavepoint");
|
||||||
$this->drv->savepointRelease();
|
$this->drv->savepointRelease();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUndoASavepoint() {
|
public function testUndoASavepoint() {
|
||||||
$this->assertEquals(1, $this->drv->savepointCreate());
|
$this->assertEquals(1, $this->drv->savepointCreate());
|
||||||
$this->assertEquals(true, $this->drv->savepointUndo());
|
$this->assertEquals(true, $this->drv->savepointUndo());
|
||||||
$this->assertException("invalid", "Db", "ExceptionSavepoint");
|
$this->assertException("invalid", "Db", "ExceptionSavepoint");
|
||||||
$this->drv->savepointUndo();
|
$this->drv->savepointUndo();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testManipulateSavepoints() {
|
public function testManipulateSavepoints() {
|
||||||
$this->assertEquals(1, $this->drv->savepointCreate());
|
$this->assertEquals(1, $this->drv->savepointCreate());
|
||||||
$this->assertEquals(2, $this->drv->savepointCreate());
|
$this->assertEquals(2, $this->drv->savepointCreate());
|
||||||
$this->assertEquals(3, $this->drv->savepointCreate());
|
$this->assertEquals(3, $this->drv->savepointCreate());
|
||||||
|
@ -144,7 +144,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->drv->savepointRelease(2);
|
$this->drv->savepointRelease(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testManipulateSavepointsSomeMore() {
|
public function testManipulateSavepointsSomeMore() {
|
||||||
$this->assertEquals(1, $this->drv->savepointCreate());
|
$this->assertEquals(1, $this->drv->savepointCreate());
|
||||||
$this->assertEquals(2, $this->drv->savepointCreate());
|
$this->assertEquals(2, $this->drv->savepointCreate());
|
||||||
$this->assertEquals(3, $this->drv->savepointCreate());
|
$this->assertEquals(3, $this->drv->savepointCreate());
|
||||||
|
@ -155,7 +155,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->drv->savepointUndo(2);
|
$this->drv->savepointUndo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBeginATransaction() {
|
public function testBeginATransaction() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
@ -168,7 +168,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals(0, $this->ch->querySingle($select));
|
$this->assertEquals(0, $this->ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCommitATransaction() {
|
public function testCommitATransaction() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
@ -181,7 +181,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals(1, $this->ch->querySingle($select));
|
$this->assertEquals(1, $this->ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRollbackATransaction() {
|
public function testRollbackATransaction() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
@ -194,7 +194,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals(0, $this->ch->querySingle($select));
|
$this->assertEquals(0, $this->ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBeginChainedTransactions() {
|
public function testBeginChainedTransactions() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
@ -208,7 +208,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals(0, $this->ch->querySingle($select));
|
$this->assertEquals(0, $this->ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCommitChainedTransactions() {
|
public function testCommitChainedTransactions() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
@ -226,7 +226,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals(2, $this->ch->querySingle($select));
|
$this->assertEquals(2, $this->ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCommitChainedTransactionsOutOfOrder() {
|
public function testCommitChainedTransactionsOutOfOrder() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
@ -243,7 +243,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$tr2->commit();
|
$tr2->commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRollbackChainedTransactions() {
|
public function testRollbackChainedTransactions() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
@ -263,7 +263,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals(0, $this->ch->querySingle($select));
|
$this->assertEquals(0, $this->ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRollbackChainedTransactionsOutOfOrder() {
|
public function testRollbackChainedTransactionsOutOfOrder() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
@ -283,7 +283,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals(0, $this->ch->querySingle($select));
|
$this->assertEquals(0, $this->ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPartiallyRollbackChainedTransactions() {
|
public function testPartiallyRollbackChainedTransactions() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
@ -303,7 +303,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals(1, $this->ch->querySingle($select));
|
$this->assertEquals(1, $this->ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchSchemaVersion() {
|
public function testFetchSchemaVersion() {
|
||||||
$this->assertSame(0, $this->drv->schemaVersion());
|
$this->assertSame(0, $this->drv->schemaVersion());
|
||||||
$this->drv->exec("PRAGMA user_version=1");
|
$this->drv->exec("PRAGMA user_version=1");
|
||||||
$this->assertSame(1, $this->drv->schemaVersion());
|
$this->assertSame(1, $this->drv->schemaVersion());
|
||||||
|
@ -311,13 +311,13 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertSame(2, $this->drv->schemaVersion());
|
$this->assertSame(2, $this->drv->schemaVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLockTheDatabase() {
|
public function testLockTheDatabase() {
|
||||||
$this->drv->savepointCreate(true);
|
$this->drv->savepointCreate(true);
|
||||||
$this->assertException();
|
$this->assertException();
|
||||||
$this->ch->exec("CREATE TABLE test(id integer primary key)");
|
$this->ch->exec("CREATE TABLE test(id integer primary key)");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUnlockTheDatabase() {
|
public function testUnlockTheDatabase() {
|
||||||
$this->drv->savepointCreate(true);
|
$this->drv->savepointCreate(true);
|
||||||
$this->drv->savepointRelease();
|
$this->drv->savepointRelease();
|
||||||
$this->drv->savepointCreate(true);
|
$this->drv->savepointCreate(true);
|
||||||
|
|
|
@ -4,10 +4,9 @@ namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\Db\SQLite3\Result<extended> */
|
/** @covers \JKingWeb\Arsse\Db\SQLite3\Result<extended> */
|
||||||
class TestDbResultSQLite3 extends Test\AbstractTest {
|
class TestDbResultSQLite3 extends Test\AbstractTest {
|
||||||
|
|
||||||
protected $c;
|
protected $c;
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
if (!extension_loaded("sqlite3")) {
|
if (!extension_loaded("sqlite3")) {
|
||||||
$this->markTestSkipped("SQLite extension not loaded");
|
$this->markTestSkipped("SQLite extension not loaded");
|
||||||
}
|
}
|
||||||
|
@ -16,17 +15,17 @@ class TestDbResultSQLite3 extends Test\AbstractTest {
|
||||||
$this->c = $c;
|
$this->c = $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
$this->c->close();
|
$this->c->close();
|
||||||
unset($this->c);
|
unset($this->c);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testConstructResult() {
|
public function testConstructResult() {
|
||||||
$set = $this->c->query("SELECT 1");
|
$set = $this->c->query("SELECT 1");
|
||||||
$this->assertInstanceOf(Db\Result::class, new Db\SQLite3\Result($set));
|
$this->assertInstanceOf(Db\Result::class, new Db\SQLite3\Result($set));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetChangeCountAndLastInsertId() {
|
public function testGetChangeCountAndLastInsertId() {
|
||||||
$this->c->query("CREATE TABLE test(col)");
|
$this->c->query("CREATE TABLE test(col)");
|
||||||
$set = $this->c->query("INSERT INTO test(col) values(1)");
|
$set = $this->c->query("INSERT INTO test(col) values(1)");
|
||||||
$rows = $this->c->changes();
|
$rows = $this->c->changes();
|
||||||
|
@ -36,7 +35,7 @@ class TestDbResultSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals($id, $r->lastId());
|
$this->assertEquals($id, $r->lastId());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testIterateOverResults() {
|
public function testIterateOverResults() {
|
||||||
$set = $this->c->query("SELECT 1 as col union select 2 as col union select 3 as col");
|
$set = $this->c->query("SELECT 1 as col union select 2 as col union select 3 as col");
|
||||||
$rows = [];
|
$rows = [];
|
||||||
foreach (new Db\SQLite3\Result($set) as $index => $row) {
|
foreach (new Db\SQLite3\Result($set) as $index => $row) {
|
||||||
|
@ -45,7 +44,7 @@ class TestDbResultSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals([0 => 1, 1 => 2, 2 => 3], $rows);
|
$this->assertEquals([0 => 1, 1 => 2, 2 => 3], $rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testIterateOverResultsTwice() {
|
public function testIterateOverResultsTwice() {
|
||||||
$set = $this->c->query("SELECT 1 as col union select 2 as col union select 3 as col");
|
$set = $this->c->query("SELECT 1 as col union select 2 as col union select 3 as col");
|
||||||
$rows = [];
|
$rows = [];
|
||||||
$test = new Db\SQLite3\Result($set);
|
$test = new Db\SQLite3\Result($set);
|
||||||
|
@ -58,7 +57,7 @@ class TestDbResultSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertEquals([1,2,3,1,2,3], $rows);
|
$this->assertEquals([1,2,3,1,2,3], $rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetSingleValues() {
|
public function testGetSingleValues() {
|
||||||
$set = $this->c->query("SELECT 1867 as year union select 1970 as year union select 2112 as year");
|
$set = $this->c->query("SELECT 1867 as year union select 1970 as year union select 2112 as year");
|
||||||
$test = new Db\SQLite3\Result($set);
|
$test = new Db\SQLite3\Result($set);
|
||||||
$this->assertEquals(1867, $test->getValue());
|
$this->assertEquals(1867, $test->getValue());
|
||||||
|
@ -67,7 +66,7 @@ class TestDbResultSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertSame(null, $test->getValue());
|
$this->assertSame(null, $test->getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetFirstValuesOnly() {
|
public function testGetFirstValuesOnly() {
|
||||||
$set = $this->c->query("SELECT 1867 as year, 19 as century union select 1970 as year, 20 as century union select 2112 as year, 22 as century");
|
$set = $this->c->query("SELECT 1867 as year, 19 as century union select 1970 as year, 20 as century union select 2112 as year, 22 as century");
|
||||||
$test = new Db\SQLite3\Result($set);
|
$test = new Db\SQLite3\Result($set);
|
||||||
$this->assertEquals(1867, $test->getValue());
|
$this->assertEquals(1867, $test->getValue());
|
||||||
|
@ -76,7 +75,7 @@ class TestDbResultSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertSame(null, $test->getValue());
|
$this->assertSame(null, $test->getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetRows() {
|
public function testGetRows() {
|
||||||
$set = $this->c->query("SELECT '2112' as album, '2112' as track union select 'Clockwork Angels' as album, 'The Wreckers' as track");
|
$set = $this->c->query("SELECT '2112' as album, '2112' as track union select 'Clockwork Angels' as album, 'The Wreckers' as track");
|
||||||
$rows = [
|
$rows = [
|
||||||
['album' => '2112', 'track' => '2112'],
|
['album' => '2112', 'track' => '2112'],
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
use JKingWeb\Arsse\Db\Statement;
|
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\Db\Statement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \JKingWeb\Arsse\Db\SQLite3\Statement<extended>
|
* @covers \JKingWeb\Arsse\Db\SQLite3\Statement<extended>
|
||||||
|
@ -11,9 +11,9 @@ class TestDbStatementSQLite3 extends Test\AbstractTest {
|
||||||
use Test\Db\BindingTests;
|
use Test\Db\BindingTests;
|
||||||
|
|
||||||
protected $c;
|
protected $c;
|
||||||
static protected $imp = Db\SQLite3\Statement::class;
|
protected static $imp = Db\SQLite3\Statement::class;
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
if (!extension_loaded("sqlite3")) {
|
if (!extension_loaded("sqlite3")) {
|
||||||
$this->markTestSkipped("SQLite extension not loaded");
|
$this->markTestSkipped("SQLite extension not loaded");
|
||||||
|
@ -23,7 +23,7 @@ class TestDbStatementSQLite3 extends Test\AbstractTest {
|
||||||
$this->c = $c;
|
$this->c = $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
$this->c->close();
|
$this->c->close();
|
||||||
unset($this->c);
|
unset($this->c);
|
||||||
}
|
}
|
||||||
|
@ -42,19 +42,19 @@ class TestDbStatementSQLite3 extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testConstructStatement() {
|
public function testConstructStatement() {
|
||||||
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
||||||
$this->assertInstanceOf(Statement::class, new Db\SQLite3\Statement($this->c, $nativeStatement));
|
$this->assertInstanceOf(Statement::class, new Db\SQLite3\Statement($this->c, $nativeStatement));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindMissingValue() {
|
public function testBindMissingValue() {
|
||||||
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
||||||
$s = new self::$imp($this->c, $nativeStatement);
|
$s = new self::$imp($this->c, $nativeStatement);
|
||||||
$val = $s->runArray()->getRow()['value'];
|
$val = $s->runArray()->getRow()['value'];
|
||||||
$this->assertSame(null, $val);
|
$this->assertSame(null, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindMultipleValues() {
|
public function testBindMultipleValues() {
|
||||||
$exp = [
|
$exp = [
|
||||||
'one' => 1,
|
'one' => 1,
|
||||||
'two' => 2,
|
'two' => 2,
|
||||||
|
@ -65,7 +65,7 @@ class TestDbStatementSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertSame($exp, $val);
|
$this->assertSame($exp, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindRecursively() {
|
public function testBindRecursively() {
|
||||||
$exp = [
|
$exp = [
|
||||||
'one' => 1,
|
'one' => 1,
|
||||||
'two' => 2,
|
'two' => 2,
|
||||||
|
@ -78,14 +78,14 @@ class TestDbStatementSQLite3 extends Test\AbstractTest {
|
||||||
$this->assertSame($exp, $val);
|
$this->assertSame($exp, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindWithoutType() {
|
public function testBindWithoutType() {
|
||||||
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
||||||
$this->assertException("paramTypeMissing", "Db");
|
$this->assertException("paramTypeMissing", "Db");
|
||||||
$s = new self::$imp($this->c, $nativeStatement, []);
|
$s = new self::$imp($this->c, $nativeStatement, []);
|
||||||
$s->runArray([1]);
|
$s->runArray([1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testViolateConstraint() {
|
public function testViolateConstraint() {
|
||||||
$this->c->exec("CREATE TABLE test(id integer not null)");
|
$this->c->exec("CREATE TABLE test(id integer not null)");
|
||||||
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)");
|
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)");
|
||||||
$s = new self::$imp($this->c, $nativeStatement, ["int"]);
|
$s = new self::$imp($this->c, $nativeStatement, ["int"]);
|
||||||
|
@ -93,7 +93,7 @@ class TestDbStatementSQLite3 extends Test\AbstractTest {
|
||||||
$s->runArray([null]);
|
$s->runArray([null]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMismatchTypes() {
|
public function testMismatchTypes() {
|
||||||
$this->c->exec("CREATE TABLE test(id integer primary key)");
|
$this->c->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)");
|
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)");
|
||||||
$s = new self::$imp($this->c, $nativeStatement, ["str"]);
|
$s = new self::$imp($this->c, $nativeStatement, ["str"]);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
use org\bovigo\vfs\vfsStream;
|
|
||||||
|
|
||||||
|
use org\bovigo\vfs\vfsStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \JKingWeb\Arsse\Db\SQLite3\Driver<extended>
|
* @covers \JKingWeb\Arsse\Db\SQLite3\Driver<extended>
|
||||||
|
@ -16,7 +16,7 @@ class TestDbUpdateSQLite3 extends Test\AbstractTest {
|
||||||
const MINIMAL1 = "create table arsse_meta(key text primary key not null, value text); pragma user_version=1";
|
const MINIMAL1 = "create table arsse_meta(key text primary key not null, value text); pragma user_version=1";
|
||||||
const MINIMAL2 = "pragma user_version=2";
|
const MINIMAL2 = "pragma user_version=2";
|
||||||
|
|
||||||
function setUp(Conf $conf = null) {
|
public function setUp(Conf $conf = null) {
|
||||||
if (!extension_loaded("sqlite3")) {
|
if (!extension_loaded("sqlite3")) {
|
||||||
$this->markTestSkipped("SQLite extension not loaded");
|
$this->markTestSkipped("SQLite extension not loaded");
|
||||||
}
|
}
|
||||||
|
@ -33,44 +33,44 @@ class TestDbUpdateSQLite3 extends Test\AbstractTest {
|
||||||
$this->drv = new Db\SQLite3\Driver(true);
|
$this->drv = new Db\SQLite3\Driver(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
unset($this->drv);
|
unset($this->drv);
|
||||||
unset($this->data);
|
unset($this->data);
|
||||||
unset($this->vfs);
|
unset($this->vfs);
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadMissingFile() {
|
public function testLoadMissingFile() {
|
||||||
$this->assertException("updateFileMissing", "Db");
|
$this->assertException("updateFileMissing", "Db");
|
||||||
$this->drv->schemaUpdate(1, $this->base);
|
$this->drv->schemaUpdate(1, $this->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadUnreadableFile() {
|
public function testLoadUnreadableFile() {
|
||||||
touch($this->path."0.sql");
|
touch($this->path."0.sql");
|
||||||
chmod($this->path."0.sql", 0000);
|
chmod($this->path."0.sql", 0000);
|
||||||
$this->assertException("updateFileUnreadable", "Db");
|
$this->assertException("updateFileUnreadable", "Db");
|
||||||
$this->drv->schemaUpdate(1, $this->base);
|
$this->drv->schemaUpdate(1, $this->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadCorruptFile() {
|
public function testLoadCorruptFile() {
|
||||||
file_put_contents($this->path."0.sql", "This is a corrupt file");
|
file_put_contents($this->path."0.sql", "This is a corrupt file");
|
||||||
$this->assertException("updateFileError", "Db");
|
$this->assertException("updateFileError", "Db");
|
||||||
$this->drv->schemaUpdate(1, $this->base);
|
$this->drv->schemaUpdate(1, $this->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadIncompleteFile() {
|
public function testLoadIncompleteFile() {
|
||||||
file_put_contents($this->path."0.sql", "create table arsse_meta(key text primary key not null, value text);");
|
file_put_contents($this->path."0.sql", "create table arsse_meta(key text primary key not null, value text);");
|
||||||
$this->assertException("updateFileIncomplete", "Db");
|
$this->assertException("updateFileIncomplete", "Db");
|
||||||
$this->drv->schemaUpdate(1, $this->base);
|
$this->drv->schemaUpdate(1, $this->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadCorrectFile() {
|
public function testLoadCorrectFile() {
|
||||||
file_put_contents($this->path."0.sql", self::MINIMAL1);
|
file_put_contents($this->path."0.sql", self::MINIMAL1);
|
||||||
$this->drv->schemaUpdate(1, $this->base);
|
$this->drv->schemaUpdate(1, $this->base);
|
||||||
$this->assertEquals(1, $this->drv->schemaVersion());
|
$this->assertEquals(1, $this->drv->schemaVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPerformPartialUpdate() {
|
public function testPerformPartialUpdate() {
|
||||||
file_put_contents($this->path."0.sql", self::MINIMAL1);
|
file_put_contents($this->path."0.sql", self::MINIMAL1);
|
||||||
file_put_contents($this->path."1.sql", "");
|
file_put_contents($this->path."1.sql", "");
|
||||||
$this->assertException("updateFileIncomplete", "Db");
|
$this->assertException("updateFileIncomplete", "Db");
|
||||||
|
@ -82,19 +82,19 @@ class TestDbUpdateSQLite3 extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPerformSequentialUpdate() {
|
public function testPerformSequentialUpdate() {
|
||||||
file_put_contents($this->path."0.sql", self::MINIMAL1);
|
file_put_contents($this->path."0.sql", self::MINIMAL1);
|
||||||
file_put_contents($this->path."1.sql", self::MINIMAL2);
|
file_put_contents($this->path."1.sql", self::MINIMAL2);
|
||||||
$this->drv->schemaUpdate(2, $this->base);
|
$this->drv->schemaUpdate(2, $this->base);
|
||||||
$this->assertEquals(2, $this->drv->schemaVersion());
|
$this->assertEquals(2, $this->drv->schemaVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPerformActualUpdate() {
|
public function testPerformActualUpdate() {
|
||||||
$this->drv->schemaUpdate(Database::SCHEMA_VERSION);
|
$this->drv->schemaUpdate(Database::SCHEMA_VERSION);
|
||||||
$this->assertEquals(Database::SCHEMA_VERSION, $this->drv->schemaVersion());
|
$this->assertEquals(Database::SCHEMA_VERSION, $this->drv->schemaVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDeclineManualUpdate() {
|
public function testDeclineManualUpdate() {
|
||||||
// turn auto-updating off
|
// turn auto-updating off
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->dbAutoUpdate = false;
|
$conf->dbAutoUpdate = false;
|
||||||
|
@ -103,7 +103,7 @@ class TestDbUpdateSQLite3 extends Test\AbstractTest {
|
||||||
$this->drv->schemaUpdate(Database::SCHEMA_VERSION);
|
$this->drv->schemaUpdate(Database::SCHEMA_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDeclineDowngrade() {
|
public function testDeclineDowngrade() {
|
||||||
$this->assertException("updateTooNew", "Db");
|
$this->assertException("updateTooNew", "Db");
|
||||||
$this->drv->schemaUpdate(-1, $this->base);
|
$this->drv->schemaUpdate(-1, $this->base);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Db\Transaction;
|
use JKingWeb\Arsse\Db\Transaction;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@ use Phake;
|
||||||
class TestTransaction extends Test\AbstractTest {
|
class TestTransaction extends Test\AbstractTest {
|
||||||
protected $drv;
|
protected $drv;
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
$drv = Phake::mock(Db\SQLite3\Driver::class);
|
$drv = Phake::mock(Db\SQLite3\Driver::class);
|
||||||
Phake::when($drv)->savepointRelease->thenReturn(true);
|
Phake::when($drv)->savepointRelease->thenReturn(true);
|
||||||
|
@ -18,7 +19,7 @@ class TestTransaction extends Test\AbstractTest {
|
||||||
$this->drv = $drv;
|
$this->drv = $drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testManipulateTransactions() {
|
public function testManipulateTransactions() {
|
||||||
$tr1 = new Transaction($this->drv);
|
$tr1 = new Transaction($this->drv);
|
||||||
$tr2 = new Transaction($this->drv);
|
$tr2 = new Transaction($this->drv);
|
||||||
Phake::verify($this->drv, Phake::times(2))->savepointCreate;
|
Phake::verify($this->drv, Phake::times(2))->savepointCreate;
|
||||||
|
@ -30,7 +31,7 @@ class TestTransaction extends Test\AbstractTest {
|
||||||
Phake::verify($this->drv)->savepointUndo(2);
|
Phake::verify($this->drv)->savepointUndo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCloseTransactions() {
|
public function testCloseTransactions() {
|
||||||
$tr1 = new Transaction($this->drv);
|
$tr1 = new Transaction($this->drv);
|
||||||
$tr2 = new Transaction($this->drv);
|
$tr2 = new Transaction($this->drv);
|
||||||
$this->assertTrue($tr1->isPending());
|
$this->assertTrue($tr1->isPending());
|
||||||
|
@ -45,7 +46,7 @@ class TestTransaction extends Test\AbstractTest {
|
||||||
Phake::verify($this->drv)->savepointUndo(2);
|
Phake::verify($this->drv)->savepointUndo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testIgnoreRollbackErrors() {
|
public function testIgnoreRollbackErrors() {
|
||||||
Phake::when($this->drv)->savepointUndo->thenThrow(new Db\ExceptionSavepoint("stale"));
|
Phake::when($this->drv)->savepointUndo->thenThrow(new Db\ExceptionSavepoint("stale"));
|
||||||
$tr1 = new Transaction($this->drv);
|
$tr1 = new Transaction($this->drv);
|
||||||
$tr2 = new Transaction($this->drv);
|
$tr2 = new Transaction($this->drv);
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
Use Phake;
|
|
||||||
|
|
||||||
|
use Phake;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\AbstractException */
|
/** @covers \JKingWeb\Arsse\AbstractException */
|
||||||
class TestException extends Test\AbstractTest {
|
class TestException extends Test\AbstractTest {
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
$this->clearData(false);
|
$this->clearData(false);
|
||||||
// create a mock Lang object so as not to create a dependency loop
|
// create a mock Lang object so as not to create a dependency loop
|
||||||
Arsse::$lang = Phake::mock(Lang::class);
|
Arsse::$lang = Phake::mock(Lang::class);
|
||||||
Phake::when(Arsse::$lang)->msg->thenReturn("");
|
Phake::when(Arsse::$lang)->msg->thenReturn("");
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
// verify calls to the mock Lang object
|
// verify calls to the mock Lang object
|
||||||
Phake::verify(Arsse::$lang, Phake::atLeast(0))->msg($this->isType("string"), $this->anything());
|
Phake::verify(Arsse::$lang, Phake::atLeast(0))->msg($this->isType("string"), $this->anything());
|
||||||
Phake::verifyNoOtherInteractions(Arsse::$lang);
|
Phake::verifyNoOtherInteractions(Arsse::$lang);
|
||||||
|
@ -21,7 +21,7 @@ class TestException extends Test\AbstractTest {
|
||||||
$this->clearData(true);
|
$this->clearData(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBaseClass() {
|
public function testBaseClass() {
|
||||||
$this->assertException("unknown");
|
$this->assertException("unknown");
|
||||||
throw new Exception("unknown");
|
throw new Exception("unknown");
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class TestException extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testBaseClass
|
* @depends testBaseClass
|
||||||
*/
|
*/
|
||||||
function testBaseClassWithoutMessage() {
|
public function testBaseClassWithoutMessage() {
|
||||||
$this->assertException("unknown");
|
$this->assertException("unknown");
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ class TestException extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testBaseClass
|
* @depends testBaseClass
|
||||||
*/
|
*/
|
||||||
function testDerivedClass() {
|
public function testDerivedClass() {
|
||||||
$this->assertException("fileMissing", "Lang");
|
$this->assertException("fileMissing", "Lang");
|
||||||
throw new Lang\Exception("fileMissing");
|
throw new Lang\Exception("fileMissing");
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ class TestException extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testDerivedClass
|
* @depends testDerivedClass
|
||||||
*/
|
*/
|
||||||
function testDerivedClassWithMessageParameters() {
|
public function testDerivedClassWithMessageParameters() {
|
||||||
$this->assertException("fileMissing", "Lang");
|
$this->assertException("fileMissing", "Lang");
|
||||||
throw new Lang\Exception("fileMissing", "en");
|
throw new Lang\Exception("fileMissing", "en");
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ class TestException extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testBaseClass
|
* @depends testBaseClass
|
||||||
*/
|
*/
|
||||||
function testBaseClassWithUnknownCode() {
|
public function testBaseClassWithUnknownCode() {
|
||||||
$this->assertException("uncoded");
|
$this->assertException("uncoded");
|
||||||
throw new Exception("testThisExceptionMessageDoesNotExist");
|
throw new Exception("testThisExceptionMessageDoesNotExist");
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ class TestException extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testBaseClassWithUnknownCode
|
* @depends testBaseClassWithUnknownCode
|
||||||
*/
|
*/
|
||||||
function testDerivedClassWithMissingMessage() {
|
public function testDerivedClassWithMissingMessage() {
|
||||||
$this->assertException("uncoded");
|
$this->assertException("uncoded");
|
||||||
throw new Lang\Exception("testThisExceptionMessageDoesNotExist");
|
throw new Lang\Exception("testThisExceptionMessageDoesNotExist");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \JKingWeb\Arsse\Feed
|
* @covers \JKingWeb\Arsse\Feed
|
||||||
* @covers \JKingWeb\Arsse\Feed\Exception */
|
* @covers \JKingWeb\Arsse\Feed\Exception */
|
||||||
|
@ -80,7 +80,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
if (!@file_get_contents(self::$host."IsUp")) {
|
if (!@file_get_contents(self::$host."IsUp")) {
|
||||||
$this->markTestSkipped("Test Web server is not accepting requests");
|
$this->markTestSkipped("Test Web server is not accepting requests");
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
Arsse::$db = Phake::mock(Database::class);
|
Arsse::$db = Phake::mock(Database::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testParseAFeed() {
|
public function testParseAFeed() {
|
||||||
// test that various properties are set on the feed and on items
|
// test that various properties are set on the feed and on items
|
||||||
$f = new Feed(null, $this->base."Parsing/Valid");
|
$f = new Feed(null, $this->base."Parsing/Valid");
|
||||||
$this->assertTrue(isset($f->lastModified));
|
$this->assertTrue(isset($f->lastModified));
|
||||||
|
@ -133,27 +133,27 @@ class TestFeed extends Test\AbstractTest {
|
||||||
$this->assertSame($categories, $f->data->items[5]->categories);
|
$this->assertSame($categories, $f->data->items[5]->categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testParseEntityExpansionAttack() {
|
public function testParseEntityExpansionAttack() {
|
||||||
$this->assertException("xmlEntity", "Feed");
|
$this->assertException("xmlEntity", "Feed");
|
||||||
new Feed(null, $this->base."Parsing/XEEAttack");
|
new Feed(null, $this->base."Parsing/XEEAttack");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testParseExternalEntityAttack() {
|
public function testParseExternalEntityAttack() {
|
||||||
$this->assertException("xmlEntity", "Feed");
|
$this->assertException("xmlEntity", "Feed");
|
||||||
new Feed(null, $this->base."Parsing/XXEAttack");
|
new Feed(null, $this->base."Parsing/XXEAttack");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testParseAnUnsupportedFeed() {
|
public function testParseAnUnsupportedFeed() {
|
||||||
$this->assertException("unsupportedFeedFormat", "Feed");
|
$this->assertException("unsupportedFeedFormat", "Feed");
|
||||||
new Feed(null, $this->base."Parsing/Unsupported");
|
new Feed(null, $this->base."Parsing/Unsupported");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testParseAMalformedFeed() {
|
public function testParseAMalformedFeed() {
|
||||||
$this->assertException("malformedXml", "Feed");
|
$this->assertException("malformedXml", "Feed");
|
||||||
new Feed(null, $this->base."Parsing/Malformed");
|
new Feed(null, $this->base."Parsing/Malformed");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDeduplicateFeedItems() {
|
public function testDeduplicateFeedItems() {
|
||||||
// duplicates with dates lead to the newest match being kept
|
// duplicates with dates lead to the newest match being kept
|
||||||
$t = strtotime("2002-05-19T15:21:36Z");
|
$t = strtotime("2002-05-19T15:21:36Z");
|
||||||
$f = new Feed(null, $this->base."Deduplication/Permalink-Dates");
|
$f = new Feed(null, $this->base."Deduplication/Permalink-Dates");
|
||||||
|
@ -180,7 +180,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
$this->assertSame("http://example.com/1", $f->newItems[0]->url);
|
$this->assertSame("http://example.com/1", $f->newItems[0]->url);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandleCacheHeadersOn304() {
|
public function testHandleCacheHeadersOn304() {
|
||||||
// upon 304, the client should re-use the caching header values it supplied the server
|
// upon 304, the client should re-use the caching header values it supplied the server
|
||||||
$t = time();
|
$t = time();
|
||||||
$e = "78567a";
|
$e = "78567a";
|
||||||
|
@ -198,7 +198,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
$this->assertSame($e, $f->resource->getETag());
|
$this->assertSame($e, $f->resource->getETag());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandleCacheHeadersOn200() {
|
public function testHandleCacheHeadersOn200() {
|
||||||
// these tests should trust the server-returned time, even in cases of obviously incorrect results
|
// these tests should trust the server-returned time, even in cases of obviously incorrect results
|
||||||
$t = time() - 2000;
|
$t = time() - 2000;
|
||||||
$f = new Feed(null, $this->base."Caching/200Past");
|
$f = new Feed(null, $this->base."Caching/200Past");
|
||||||
|
@ -226,7 +226,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
$this->assertTime($t, $f->lastModified);
|
$this->assertTime($t, $f->lastModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testComputeNextFetchOnError() {
|
public function testComputeNextFetchOnError() {
|
||||||
for ($a = 0; $a < 100; $a++) {
|
for ($a = 0; $a < 100; $a++) {
|
||||||
if ($a < 3) {
|
if ($a < 3) {
|
||||||
$this->assertTime("now + 5 minutes", Feed::nextFetchOnError($a));
|
$this->assertTime("now + 5 minutes", Feed::nextFetchOnError($a));
|
||||||
|
@ -238,7 +238,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testComputeNextFetchFrom304() {
|
public function testComputeNextFetchFrom304() {
|
||||||
// if less than half an hour, check in 15 minutes
|
// if less than half an hour, check in 15 minutes
|
||||||
$t = strtotime("now");
|
$t = strtotime("now");
|
||||||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http"));
|
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http"));
|
||||||
|
@ -286,7 +286,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
$this->assertTime($exp, $f->nextFetch);
|
$this->assertTime($exp, $f->nextFetch);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testComputeNextFetchFrom200() {
|
public function testComputeNextFetchFrom200() {
|
||||||
// if less than half an hour, check in 15 minutes
|
// if less than half an hour, check in 15 minutes
|
||||||
$f = new Feed(null, $this->base."NextFetch/30m");
|
$f = new Feed(null, $this->base."NextFetch/30m");
|
||||||
$exp = strtotime("now + 15 minutes");
|
$exp = strtotime("now + 15 minutes");
|
||||||
|
@ -313,7 +313,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
$this->assertTime($exp, $f->nextFetch);
|
$this->assertTime($exp, $f->nextFetch);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMatchLatestArticles() {
|
public function testMatchLatestArticles() {
|
||||||
Phake::when(Arsse::$db)->feedMatchLatest(1, $this->anything())->thenReturn(new Test\Result($this->latest));
|
Phake::when(Arsse::$db)->feedMatchLatest(1, $this->anything())->thenReturn(new Test\Result($this->latest));
|
||||||
$f = new Feed(1, $this->base."Matching/1");
|
$f = new Feed(1, $this->base."Matching/1");
|
||||||
$this->assertCount(0, $f->newItems);
|
$this->assertCount(0, $f->newItems);
|
||||||
|
@ -329,7 +329,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
$this->assertCount(2, $f->changedItems);
|
$this->assertCount(2, $f->changedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMatchHistoricalArticles() {
|
public function testMatchHistoricalArticles() {
|
||||||
Phake::when(Arsse::$db)->feedMatchLatest(1, $this->anything())->thenReturn(new Test\Result($this->latest));
|
Phake::when(Arsse::$db)->feedMatchLatest(1, $this->anything())->thenReturn(new Test\Result($this->latest));
|
||||||
Phake::when(Arsse::$db)->feedMatchIds(1, $this->anything(), $this->anything(), $this->anything(), $this->anything())->thenReturn(new Test\Result($this->others));
|
Phake::when(Arsse::$db)->feedMatchIds(1, $this->anything(), $this->anything(), $this->anything(), $this->anything())->thenReturn(new Test\Result($this->others));
|
||||||
$f = new Feed(1, $this->base."Matching/5");
|
$f = new Feed(1, $this->base."Matching/5");
|
||||||
|
@ -337,7 +337,7 @@ class TestFeed extends Test\AbstractTest {
|
||||||
$this->assertCount(0, $f->changedItems);
|
$this->assertCount(0, $f->changedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testScrapeFullContent() {
|
public function testScrapeFullContent() {
|
||||||
// first make sure that the absence of scraping works as expected
|
// first make sure that the absence of scraping works as expected
|
||||||
$f = new Feed(null, $this->base."Scraping/Feed");
|
$f = new Feed(null, $this->base."Scraping/Feed");
|
||||||
$exp = "<p>Partial content</p>";
|
$exp = "<p>Partial content</p>";
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
Use Phake;
|
|
||||||
|
|
||||||
|
use Phake;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\Feed */
|
/** @covers \JKingWeb\Arsse\Feed */
|
||||||
class TestFeedFetching extends Test\AbstractTest {
|
class TestFeedFetching extends Test\AbstractTest {
|
||||||
protected static $host = "http://localhost:8000/";
|
protected static $host = "http://localhost:8000/";
|
||||||
protected $base = "";
|
protected $base = "";
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
if (!extension_loaded('curl')) {
|
if (!extension_loaded('curl')) {
|
||||||
$this->markTestSkipped("Feed fetching tests are only accurate with curl enabled.");
|
$this->markTestSkipped("Feed fetching tests are only accurate with curl enabled.");
|
||||||
} elseif (!@file_get_contents(self::$host."IsUp")) {
|
} elseif (!@file_get_contents(self::$host."IsUp")) {
|
||||||
|
@ -20,49 +20,49 @@ class TestFeedFetching extends Test\AbstractTest {
|
||||||
Arsse::$conf = new Conf();
|
Arsse::$conf = new Conf();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandle400() {
|
public function testHandle400() {
|
||||||
$this->assertException("unsupportedFeedFormat", "Feed");
|
$this->assertException("unsupportedFeedFormat", "Feed");
|
||||||
new Feed(null, $this->base."Fetching/Error?code=400");
|
new Feed(null, $this->base."Fetching/Error?code=400");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandle401() {
|
public function testHandle401() {
|
||||||
$this->assertException("unauthorized", "Feed");
|
$this->assertException("unauthorized", "Feed");
|
||||||
new Feed(null, $this->base."Fetching/Error?code=401");
|
new Feed(null, $this->base."Fetching/Error?code=401");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandle403() {
|
public function testHandle403() {
|
||||||
$this->assertException("forbidden", "Feed");
|
$this->assertException("forbidden", "Feed");
|
||||||
new Feed(null, $this->base."Fetching/Error?code=403");
|
new Feed(null, $this->base."Fetching/Error?code=403");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandle404() {
|
public function testHandle404() {
|
||||||
$this->assertException("invalidUrl", "Feed");
|
$this->assertException("invalidUrl", "Feed");
|
||||||
new Feed(null, $this->base."Fetching/Error?code=404");
|
new Feed(null, $this->base."Fetching/Error?code=404");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandle500() {
|
public function testHandle500() {
|
||||||
$this->assertException("unsupportedFeedFormat", "Feed");
|
$this->assertException("unsupportedFeedFormat", "Feed");
|
||||||
new Feed(null, $this->base."Fetching/Error?code=500");
|
new Feed(null, $this->base."Fetching/Error?code=500");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandleARedirectLoop() {
|
public function testHandleARedirectLoop() {
|
||||||
$this->assertException("maxRedirect", "Feed");
|
$this->assertException("maxRedirect", "Feed");
|
||||||
new Feed(null, $this->base."Fetching/EndlessLoop?i=0");
|
new Feed(null, $this->base."Fetching/EndlessLoop?i=0");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandleATimeout() {
|
public function testHandleATimeout() {
|
||||||
Arsse::$conf->fetchTimeout = 1;
|
Arsse::$conf->fetchTimeout = 1;
|
||||||
$this->assertException("timeout", "Feed");
|
$this->assertException("timeout", "Feed");
|
||||||
new Feed(null, $this->base."Fetching/Timeout");
|
new Feed(null, $this->base."Fetching/Timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandleAnOverlyLargeFeed() {
|
public function testHandleAnOverlyLargeFeed() {
|
||||||
Arsse::$conf->fetchSizeLimit = 512;
|
Arsse::$conf->fetchSizeLimit = 512;
|
||||||
$this->assertException("maxSize", "Feed");
|
$this->assertException("maxSize", "Feed");
|
||||||
new Feed(null, $this->base."Fetching/TooLarge");
|
new Feed(null, $this->base."Fetching/TooLarge");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHandleACertificateError() {
|
public function testHandleACertificateError() {
|
||||||
$this->assertException("invalidCertificate", "Feed");
|
$this->assertException("invalidCertificate", "Feed");
|
||||||
new Feed(null, "https://localhost:8000/");
|
new Feed(null, "https://localhost:8000/");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use org\bovigo\vfs\vfsStream;
|
use org\bovigo\vfs\vfsStream;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\Lang */
|
/** @covers \JKingWeb\Arsse\Lang */
|
||||||
|
@ -11,14 +12,14 @@ class TestLang extends Test\AbstractTest {
|
||||||
public $path;
|
public $path;
|
||||||
public $l;
|
public $l;
|
||||||
|
|
||||||
function testListLanguages() {
|
public function testListLanguages() {
|
||||||
$this->assertCount(sizeof($this->files), $this->l->list("en"));
|
$this->assertCount(sizeof($this->files), $this->l->list("en"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @depends testListLanguages
|
* @depends testListLanguages
|
||||||
*/
|
*/
|
||||||
function testSetLanguage() {
|
public function testSetLanguage() {
|
||||||
$this->assertEquals("en", $this->l->set("en"));
|
$this->assertEquals("en", $this->l->set("en"));
|
||||||
$this->assertEquals("en_ca", $this->l->set("en_ca"));
|
$this->assertEquals("en_ca", $this->l->set("en_ca"));
|
||||||
$this->assertEquals("de", $this->l->set("de_ch"));
|
$this->assertEquals("de", $this->l->set("de_ch"));
|
||||||
|
@ -31,7 +32,7 @@ class TestLang extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testSetLanguage
|
* @depends testSetLanguage
|
||||||
*/
|
*/
|
||||||
function testLoadInternalStrings() {
|
public function testLoadInternalStrings() {
|
||||||
$this->assertEquals("", $this->l->set("", true));
|
$this->assertEquals("", $this->l->set("", true));
|
||||||
$this->assertCount(sizeof(Lang::REQUIRED), $this->l->dump());
|
$this->assertCount(sizeof(Lang::REQUIRED), $this->l->dump());
|
||||||
}
|
}
|
||||||
|
@ -39,7 +40,7 @@ class TestLang extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testLoadInternalStrings
|
* @depends testLoadInternalStrings
|
||||||
*/
|
*/
|
||||||
function testLoadDefaultLanguage() {
|
public function testLoadDefaultLanguage() {
|
||||||
$this->assertEquals(Lang::DEFAULT, $this->l->set(Lang::DEFAULT, true));
|
$this->assertEquals(Lang::DEFAULT, $this->l->set(Lang::DEFAULT, true));
|
||||||
$str = $this->l->dump();
|
$str = $this->l->dump();
|
||||||
$this->assertArrayHasKey('Exception.JKingWeb/Arsse/Exception.uncoded', $str);
|
$this->assertArrayHasKey('Exception.JKingWeb/Arsse/Exception.uncoded', $str);
|
||||||
|
@ -49,7 +50,7 @@ class TestLang extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testLoadDefaultLanguage
|
* @depends testLoadDefaultLanguage
|
||||||
*/
|
*/
|
||||||
function testLoadSupplementaryLanguage() {
|
public function testLoadSupplementaryLanguage() {
|
||||||
$this->l->set(Lang::DEFAULT, true);
|
$this->l->set(Lang::DEFAULT, true);
|
||||||
$this->assertEquals("ja", $this->l->set("ja", true));
|
$this->assertEquals("ja", $this->l->set("ja", true));
|
||||||
$str = $this->l->dump();
|
$str = $this->l->dump();
|
||||||
|
@ -57,5 +58,4 @@ class TestLang extends Test\AbstractTest {
|
||||||
$this->assertArrayHasKey('Test.presentText', $str);
|
$this->assertArrayHasKey('Test.presentText', $str);
|
||||||
$this->assertArrayHasKey('Test.absentText', $str);
|
$this->assertArrayHasKey('Test.absentText', $str);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use org\bovigo\vfs\vfsStream;
|
use org\bovigo\vfs\vfsStream;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\Lang */
|
/** @covers \JKingWeb\Arsse\Lang */
|
||||||
|
@ -11,52 +12,52 @@ class TestLangErrors extends Test\AbstractTest {
|
||||||
public $path;
|
public $path;
|
||||||
public $l;
|
public $l;
|
||||||
|
|
||||||
function setUpSeries() {
|
public function setUpSeries() {
|
||||||
$this->l->set("", true);
|
$this->l->set("", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadEmptyFile() {
|
public function testLoadEmptyFile() {
|
||||||
$this->assertException("fileCorrupt", "Lang");
|
$this->assertException("fileCorrupt", "Lang");
|
||||||
$this->l->set("fr_ca", true);
|
$this->l->set("fr_ca", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadFileWhichDoesNotReturnAnArray() {
|
public function testLoadFileWhichDoesNotReturnAnArray() {
|
||||||
$this->assertException("fileCorrupt", "Lang");
|
$this->assertException("fileCorrupt", "Lang");
|
||||||
$this->l->set("it", true);
|
$this->l->set("it", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadFileWhichIsNotPhp() {
|
public function testLoadFileWhichIsNotPhp() {
|
||||||
$this->assertException("fileCorrupt", "Lang");
|
$this->assertException("fileCorrupt", "Lang");
|
||||||
$this->l->set("ko", true);
|
$this->l->set("ko", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadFileWhichIsCorrupt() {
|
public function testLoadFileWhichIsCorrupt() {
|
||||||
$this->assertException("fileCorrupt", "Lang");
|
$this->assertException("fileCorrupt", "Lang");
|
||||||
$this->l->set("zh", true);
|
$this->l->set("zh", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadFileWithooutReadPermission() {
|
public function testLoadFileWithooutReadPermission() {
|
||||||
$this->assertException("fileUnreadable", "Lang");
|
$this->assertException("fileUnreadable", "Lang");
|
||||||
$this->l->set("ru", true);
|
$this->l->set("ru", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadSubtagOfMissingLanguage() {
|
public function testLoadSubtagOfMissingLanguage() {
|
||||||
$this->assertException("fileMissing", "Lang");
|
$this->assertException("fileMissing", "Lang");
|
||||||
$this->l->set("pt_br", true);
|
$this->l->set("pt_br", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchInvalidMessage() {
|
public function testFetchInvalidMessage() {
|
||||||
$this->assertException("stringInvalid", "Lang");
|
$this->assertException("stringInvalid", "Lang");
|
||||||
$this->l->set("vi", true);
|
$this->l->set("vi", true);
|
||||||
$txt = $this->l->msg('Test.presentText');
|
$txt = $this->l->msg('Test.presentText');
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchMissingMessage() {
|
public function testFetchMissingMessage() {
|
||||||
$this->assertException("stringMissing", "Lang");
|
$this->assertException("stringMissing", "Lang");
|
||||||
$txt = $this->l->msg('Test.absentText');
|
$txt = $this->l->msg('Test.absentText');
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadMissingDefaultLanguage() {
|
public function testLoadMissingDefaultLanguage() {
|
||||||
unlink($this->path.Lang::DEFAULT.".php");
|
unlink($this->path.Lang::DEFAULT.".php");
|
||||||
$this->assertException("defaultFileMissing", "Lang");
|
$this->assertException("defaultFileMissing", "Lang");
|
||||||
$this->l->set("fr", true);
|
$this->l->set("fr", true);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use org\bovigo\vfs\vfsStream;
|
use org\bovigo\vfs\vfsStream;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\Lang */
|
/** @covers \JKingWeb\Arsse\Lang */
|
||||||
|
@ -11,11 +12,11 @@ class TestLangComplex extends Test\AbstractTest {
|
||||||
public $path;
|
public $path;
|
||||||
public $l;
|
public $l;
|
||||||
|
|
||||||
function setUpSeries() {
|
public function setUpSeries() {
|
||||||
$this->l->set(Lang::DEFAULT, true);
|
$this->l->set(Lang::DEFAULT, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLazyLoad() {
|
public function testLazyLoad() {
|
||||||
$this->l->set("ja");
|
$this->l->set("ja");
|
||||||
$this->assertArrayNotHasKey('Test.absentText', $this->l->dump());
|
$this->assertArrayNotHasKey('Test.absentText', $this->l->dump());
|
||||||
}
|
}
|
||||||
|
@ -23,14 +24,14 @@ class TestLangComplex extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testLazyLoad
|
* @depends testLazyLoad
|
||||||
*/
|
*/
|
||||||
function testGetWantedAndLoadedLocale() {
|
public function testGetWantedAndLoadedLocale() {
|
||||||
$this->l->set("en", true);
|
$this->l->set("en", true);
|
||||||
$this->l->set("ja");
|
$this->l->set("ja");
|
||||||
$this->assertEquals("ja", $this->l->get());
|
$this->assertEquals("ja", $this->l->get());
|
||||||
$this->assertEquals("en", $this->l->get(true));
|
$this->assertEquals("en", $this->l->get(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadCascadeOfFiles() {
|
public function testLoadCascadeOfFiles() {
|
||||||
$this->l->set("ja", true);
|
$this->l->set("ja", true);
|
||||||
$this->assertEquals("de", $this->l->set("de", true));
|
$this->assertEquals("de", $this->l->set("de", true));
|
||||||
$str = $this->l->dump();
|
$str = $this->l->dump();
|
||||||
|
@ -41,11 +42,11 @@ class TestLangComplex extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testLoadCascadeOfFiles
|
* @depends testLoadCascadeOfFiles
|
||||||
*/
|
*/
|
||||||
function testLoadSubtag() {
|
public function testLoadSubtag() {
|
||||||
$this->assertEquals("en_ca", $this->l->set("en_ca", true));
|
$this->assertEquals("en_ca", $this->l->set("en_ca", true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchAMessage() {
|
public function testFetchAMessage() {
|
||||||
$this->l->set("de", true);
|
$this->l->set("de", true);
|
||||||
$this->assertEquals('und der Stein der Weisen', $this->l->msg('Test.presentText'));
|
$this->assertEquals('und der Stein der Weisen', $this->l->msg('Test.presentText'));
|
||||||
}
|
}
|
||||||
|
@ -53,7 +54,7 @@ class TestLangComplex extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testFetchAMessage
|
* @depends testFetchAMessage
|
||||||
*/
|
*/
|
||||||
function testFetchAMessageWithMissingParameters() {
|
public function testFetchAMessageWithMissingParameters() {
|
||||||
$this->l->set("en_ca", true);
|
$this->l->set("en_ca", true);
|
||||||
$this->assertEquals('{0} and {1}', $this->l->msg('Test.presentText'));
|
$this->assertEquals('{0} and {1}', $this->l->msg('Test.presentText'));
|
||||||
}
|
}
|
||||||
|
@ -61,7 +62,7 @@ class TestLangComplex extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testFetchAMessage
|
* @depends testFetchAMessage
|
||||||
*/
|
*/
|
||||||
function testFetchAMessageWithSingleNumericParameter() {
|
public function testFetchAMessageWithSingleNumericParameter() {
|
||||||
$this->l->set("en_ca", true);
|
$this->l->set("en_ca", true);
|
||||||
$this->assertEquals('Default language file "en" missing', $this->l->msg('Exception.JKingWeb/Arsse/Lang/Exception.defaultFileMissing', Lang::DEFAULT));
|
$this->assertEquals('Default language file "en" missing', $this->l->msg('Exception.JKingWeb/Arsse/Lang/Exception.defaultFileMissing', Lang::DEFAULT));
|
||||||
}
|
}
|
||||||
|
@ -69,7 +70,7 @@ class TestLangComplex extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testFetchAMessage
|
* @depends testFetchAMessage
|
||||||
*/
|
*/
|
||||||
function testFetchAMessageWithMultipleNumericParameters() {
|
public function testFetchAMessageWithMultipleNumericParameters() {
|
||||||
$this->l->set("en_ca", true);
|
$this->l->set("en_ca", true);
|
||||||
$this->assertEquals('Happy Rotter and the Philosopher\'s Stone', $this->l->msg('Test.presentText', ['Happy Rotter', 'the Philosopher\'s Stone']));
|
$this->assertEquals('Happy Rotter and the Philosopher\'s Stone', $this->l->msg('Test.presentText', ['Happy Rotter', 'the Philosopher\'s Stone']));
|
||||||
}
|
}
|
||||||
|
@ -77,14 +78,14 @@ class TestLangComplex extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testFetchAMessage
|
* @depends testFetchAMessage
|
||||||
*/
|
*/
|
||||||
function testFetchAMessageWithNamedParameters() {
|
public function testFetchAMessageWithNamedParameters() {
|
||||||
$this->assertEquals('Message string "Test.absentText" missing from all loaded language files (en)', $this->l->msg('Exception.JKingWeb/Arsse/Lang/Exception.stringMissing', ['msgID' => 'Test.absentText', 'fileList' => 'en']));
|
$this->assertEquals('Message string "Test.absentText" missing from all loaded language files (en)', $this->l->msg('Exception.JKingWeb/Arsse/Lang/Exception.stringMissing', ['msgID' => 'Test.absentText', 'fileList' => 'en']));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @depends testFetchAMessage
|
* @depends testFetchAMessage
|
||||||
*/
|
*/
|
||||||
function testReloadDefaultStrings() {
|
public function testReloadDefaultStrings() {
|
||||||
$this->l->set("de", true);
|
$this->l->set("de", true);
|
||||||
$this->l->set("en", true);
|
$this->l->set("en", true);
|
||||||
$this->assertEquals('and the Philosopher\'s Stone', $this->l->msg('Test.presentText'));
|
$this->assertEquals('and the Philosopher\'s Stone', $this->l->msg('Test.presentText'));
|
||||||
|
@ -93,7 +94,7 @@ class TestLangComplex extends Test\AbstractTest {
|
||||||
/**
|
/**
|
||||||
* @depends testFetchAMessage
|
* @depends testFetchAMessage
|
||||||
*/
|
*/
|
||||||
function testReloadGeneralTagAfterSubtag() {
|
public function testReloadGeneralTagAfterSubtag() {
|
||||||
$this->l->set("en", true);
|
$this->l->set("en", true);
|
||||||
$this->l->set("en_us", true);
|
$this->l->set("en_us", true);
|
||||||
$this->assertEquals('and the Sorcerer\'s Stone', $this->l->msg('Test.presentText'));
|
$this->assertEquals('and the Sorcerer\'s Stone', $this->l->msg('Test.presentText'));
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
use JKingWeb\Arsse\Misc\Context;
|
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\Misc\Context;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\Misc\Context */
|
/** @covers \JKingWeb\Arsse\Misc\Context */
|
||||||
class TestContext extends Test\AbstractTest {
|
class TestContext extends Test\AbstractTest {
|
||||||
function testVerifyInitialState() {
|
public function testVerifyInitialState() {
|
||||||
$c = new Context;
|
$c = new Context;
|
||||||
foreach ((new \ReflectionObject($c))->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) {
|
foreach ((new \ReflectionObject($c))->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) {
|
||||||
if ($m->isConstructor() || $m->isStatic()) {
|
if ($m->isConstructor() || $m->isStatic()) {
|
||||||
|
@ -18,7 +18,7 @@ class TestContext extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetContextOptions() {
|
public function testSetContextOptions() {
|
||||||
$v = [
|
$v = [
|
||||||
'reverse' => true,
|
'reverse' => true,
|
||||||
'limit' => 10,
|
'limit' => 10,
|
||||||
|
@ -54,7 +54,7 @@ class TestContext extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCleanArrayValues() {
|
public function testCleanArrayValues() {
|
||||||
$methods = ["articles", "editions"];
|
$methods = ["articles", "editions"];
|
||||||
$in = [1, "2", 3.5, 3.0, "ook", 0, -20, true, false, null, new \DateTime(), -1.0];
|
$in = [1, "2", 3.5, 3.0, "ook", 0, -20, true, false, null, new \DateTime(), -1.0];
|
||||||
$out = [1,2, 3];
|
$out = [1,2, 3];
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use JKingWeb\Arsse\REST\Request;
|
use JKingWeb\Arsse\REST\Request;
|
||||||
use JKingWeb\Arsse\REST\Response;
|
use JKingWeb\Arsse\REST\Response;
|
||||||
use JKingWeb\Arsse\Test\Result;
|
use JKingWeb\Arsse\Test\Result;
|
||||||
|
@ -259,7 +260,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
Arsse::$conf = new Conf();
|
Arsse::$conf = new Conf();
|
||||||
// create a mock user manager
|
// create a mock user manager
|
||||||
|
@ -268,16 +269,16 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
Phake::when(Arsse::$user)->rightsGet->thenReturn(100);
|
Phake::when(Arsse::$user)->rightsGet->thenReturn(100);
|
||||||
Arsse::$user->id = "john.doe@example.com";
|
Arsse::$user->id = "john.doe@example.com";
|
||||||
// create a mock database interface
|
// create a mock database interface
|
||||||
Arsse::$db = Phake::mock(Database::Class);
|
Arsse::$db = Phake::mock(Database::class);
|
||||||
Phake::when(Arsse::$db)->begin->thenReturn(Phake::mock(Transaction::class));
|
Phake::when(Arsse::$db)->begin->thenReturn(Phake::mock(Transaction::class));
|
||||||
$this->h = new REST\NextCloudNews\V1_2();
|
$this->h = new REST\NextCloudNews\V1_2();
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRespondToInvalidPaths() {
|
public function testRespondToInvalidPaths() {
|
||||||
$errs = [
|
$errs = [
|
||||||
501 => [
|
501 => [
|
||||||
['GET', "/"],
|
['GET', "/"],
|
||||||
|
@ -323,20 +324,20 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRespondToInvalidInputTypes() {
|
public function testRespondToInvalidInputTypes() {
|
||||||
$exp = new Response(415, "", "", ['Accept: application/json']);
|
$exp = new Response(415, "", "", ['Accept: application/json']);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", '<data/>', 'application/xml')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", '<data/>', 'application/xml')));
|
||||||
$exp = new Response(400);
|
$exp = new Response(400);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", '<data/>', 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", '<data/>', 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testReceiveAuthenticationChallenge() {
|
public function testReceiveAuthenticationChallenge() {
|
||||||
Phake::when(Arsse::$user)->authHTTP->thenReturn(false);
|
Phake::when(Arsse::$user)->authHTTP->thenReturn(false);
|
||||||
$exp = new Response(401, "", "", ['WWW-Authenticate: Basic realm="'.REST\NextCloudNews\V1_2::REALM.'"']);
|
$exp = new Response(401, "", "", ['WWW-Authenticate: Basic realm="'.REST\NextCloudNews\V1_2::REALM.'"']);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListFolders() {
|
public function testListFolders() {
|
||||||
$list = [
|
$list = [
|
||||||
['id' => 1, 'name' => "Software", 'parent' => null],
|
['id' => 1, 'name' => "Software", 'parent' => null],
|
||||||
['id' => 12, 'name' => "Hardware", 'parent' => null],
|
['id' => 12, 'name' => "Hardware", 'parent' => null],
|
||||||
|
@ -348,7 +349,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/folders")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/folders")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddAFolder() {
|
public function testAddAFolder() {
|
||||||
$in = [
|
$in = [
|
||||||
["name" => "Software"],
|
["name" => "Software"],
|
||||||
["name" => "Hardware"],
|
["name" => "Hardware"],
|
||||||
|
@ -387,7 +388,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", json_encode($in[1]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", json_encode($in[1]), 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAFolder() {
|
public function testRemoveAFolder() {
|
||||||
Phake::when(Arsse::$db)->folderRemove(Arsse::$user->id, 1)->thenReturn(true)->thenThrow(new ExceptionInput("subjectMissing"));
|
Phake::when(Arsse::$db)->folderRemove(Arsse::$user->id, 1)->thenReturn(true)->thenThrow(new ExceptionInput("subjectMissing"));
|
||||||
$exp = new Response(204);
|
$exp = new Response(204);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/1")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/1")));
|
||||||
|
@ -397,7 +398,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
Phake::verify(Arsse::$db, Phake::times(2))->folderRemove(Arsse::$user->id, 1);
|
Phake::verify(Arsse::$db, Phake::times(2))->folderRemove(Arsse::$user->id, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameAFolder() {
|
public function testRenameAFolder() {
|
||||||
$in = [
|
$in = [
|
||||||
["name" => "Software"],
|
["name" => "Software"],
|
||||||
["name" => "Software"],
|
["name" => "Software"],
|
||||||
|
@ -425,7 +426,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/3", json_encode($in[0]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/3", json_encode($in[0]), 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRetrieveServerVersion() {
|
public function testRetrieveServerVersion() {
|
||||||
$exp = new Response(200, [
|
$exp = new Response(200, [
|
||||||
'arsse_version' => \JKingWeb\Arsse\VERSION,
|
'arsse_version' => \JKingWeb\Arsse\VERSION,
|
||||||
'version' => REST\NextCloudNews\V1_2::VERSION,
|
'version' => REST\NextCloudNews\V1_2::VERSION,
|
||||||
|
@ -433,7 +434,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/version")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/version")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListSubscriptions() {
|
public function testListSubscriptions() {
|
||||||
$exp1 = [
|
$exp1 = [
|
||||||
'feeds' => [],
|
'feeds' => [],
|
||||||
'starredCount' => 0,
|
'starredCount' => 0,
|
||||||
|
@ -452,7 +453,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddASubscription() {
|
public function testAddASubscription() {
|
||||||
$in = [
|
$in = [
|
||||||
['url' => "http://example.com/news.atom", 'folderId' => 3],
|
['url' => "http://example.com/news.atom", 'folderId' => 3],
|
||||||
['url' => "http://example.org/news.atom", 'folderId' => 8],
|
['url' => "http://example.org/news.atom", 'folderId' => 8],
|
||||||
|
@ -494,7 +495,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[3]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/feeds", json_encode($in[3]), 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveASubscription() {
|
public function testRemoveASubscription() {
|
||||||
Phake::when(Arsse::$db)->subscriptionRemove(Arsse::$user->id, 1)->thenReturn(true)->thenThrow(new ExceptionInput("subjectMissing"));
|
Phake::when(Arsse::$db)->subscriptionRemove(Arsse::$user->id, 1)->thenReturn(true)->thenThrow(new ExceptionInput("subjectMissing"));
|
||||||
$exp = new Response(204);
|
$exp = new Response(204);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/feeds/1")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/feeds/1")));
|
||||||
|
@ -504,7 +505,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
Phake::verify(Arsse::$db, Phake::times(2))->subscriptionRemove(Arsse::$user->id, 1);
|
Phake::verify(Arsse::$db, Phake::times(2))->subscriptionRemove(Arsse::$user->id, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMoveASubscription() {
|
public function testMoveASubscription() {
|
||||||
$in = [
|
$in = [
|
||||||
['folderId' => 0],
|
['folderId' => 0],
|
||||||
['folderId' => 42],
|
['folderId' => 42],
|
||||||
|
@ -528,7 +529,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[4]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/move", json_encode($in[4]), 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameASubscription() {
|
public function testRenameASubscription() {
|
||||||
$in = [
|
$in = [
|
||||||
['feedTitle' => null],
|
['feedTitle' => null],
|
||||||
['feedTitle' => "Ook"],
|
['feedTitle' => "Ook"],
|
||||||
|
@ -558,7 +559,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[6]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/rename", json_encode($in[6]), 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListStaleFeeds() {
|
public function testListStaleFeeds() {
|
||||||
$out = [
|
$out = [
|
||||||
[
|
[
|
||||||
'id' => 42,
|
'id' => 42,
|
||||||
|
@ -578,7 +579,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds/all")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds/all")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUpdateAFeed() {
|
public function testUpdateAFeed() {
|
||||||
$in = [
|
$in = [
|
||||||
['feedId' => 42], // valid
|
['feedId' => 42], // valid
|
||||||
['feedId' => 2112], // feed does not exist
|
['feedId' => 2112], // feed does not exist
|
||||||
|
@ -601,7 +602,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[0]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/feeds/update", json_encode($in[0]), 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListArticles() {
|
public function testListArticles() {
|
||||||
$res = new Result($this->articles['db']);
|
$res = new Result($this->articles['db']);
|
||||||
$t = new \DateTime;
|
$t = new \DateTime;
|
||||||
$in = [
|
$in = [
|
||||||
|
@ -648,7 +649,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
Phake::verify(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->reverse(true)->limit(5));
|
Phake::verify(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->reverse(true)->limit(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAFolderRead() {
|
public function testMarkAFolderRead() {
|
||||||
$read = ['read' => true];
|
$read = ['read' => true];
|
||||||
$in = json_encode(['newestItemId' => 2112]);
|
$in = json_encode(['newestItemId' => 2112]);
|
||||||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->folder(1)->latestEdition(2112))->thenReturn(true);
|
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->folder(1)->latestEdition(2112))->thenReturn(true);
|
||||||
|
@ -663,7 +664,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/42/read", $in, 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/42/read", $in, 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkASubscriptionRead() {
|
public function testMarkASubscriptionRead() {
|
||||||
$read = ['read' => true];
|
$read = ['read' => true];
|
||||||
$in = json_encode(['newestItemId' => 2112]);
|
$in = json_encode(['newestItemId' => 2112]);
|
||||||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->subscription(1)->latestEdition(2112))->thenReturn(true);
|
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->subscription(1)->latestEdition(2112))->thenReturn(true);
|
||||||
|
@ -678,7 +679,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/42/read", $in, 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/42/read", $in, 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAllItemsRead() {
|
public function testMarkAllItemsRead() {
|
||||||
$read = ['read' => true];
|
$read = ['read' => true];
|
||||||
$in = json_encode(['newestItemId' => 2112]);
|
$in = json_encode(['newestItemId' => 2112]);
|
||||||
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->latestEdition(2112))->thenReturn(true);
|
Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->latestEdition(2112))->thenReturn(true);
|
||||||
|
@ -690,7 +691,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/items/read?newestItemId=ook")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/items/read?newestItemId=ook")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testChangeMarksOfASingleArticle() {
|
public function testChangeMarksOfASingleArticle() {
|
||||||
$read = ['read' => true];
|
$read = ['read' => true];
|
||||||
$unread = ['read' => false];
|
$unread = ['read' => false];
|
||||||
$star = ['starred' => true];
|
$star = ['starred' => true];
|
||||||
|
@ -716,7 +717,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
Phake::verify(Arsse::$db, Phake::times(8))->articleMark(Arsse::$user->id, $this->anything(), $this->anything());
|
Phake::verify(Arsse::$db, Phake::times(8))->articleMark(Arsse::$user->id, $this->anything(), $this->anything());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testChangeMarksOfMultipleArticles() {
|
public function testChangeMarksOfMultipleArticles() {
|
||||||
$read = ['read' => true];
|
$read = ['read' => true];
|
||||||
$unread = ['read' => false];
|
$unread = ['read' => false];
|
||||||
$star = ['starred' => true];
|
$star = ['starred' => true];
|
||||||
|
@ -783,7 +784,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
Phake::verify(Arsse::$db)->articleMark(Arsse::$user->id, $unstar, (new Context)->articles($in[3]));
|
Phake::verify(Arsse::$db)->articleMark(Arsse::$user->id, $unstar, (new Context)->articles($in[3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testQueryTheServerStatus() {
|
public function testQueryTheServerStatus() {
|
||||||
$interval = Service::interval();
|
$interval = Service::interval();
|
||||||
$valid = (new \DateTimeImmutable("now", new \DateTimezone("UTC")))->sub($interval);
|
$valid = (new \DateTimeImmutable("now", new \DateTimezone("UTC")))->sub($interval);
|
||||||
$invalid = $valid->sub($interval)->sub($interval);
|
$invalid = $valid->sub($interval)->sub($interval);
|
||||||
|
@ -800,7 +801,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/status")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/status")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCleanUpBeforeUpdate() {
|
public function testCleanUpBeforeUpdate() {
|
||||||
Phake::when(Arsse::$db)->feedCleanup()->thenReturn(true);
|
Phake::when(Arsse::$db)->feedCleanup()->thenReturn(true);
|
||||||
$exp = new Response(204);
|
$exp = new Response(204);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/before-update")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/before-update")));
|
||||||
|
@ -811,7 +812,7 @@ class TestNCNV1_2 extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/before-update")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/before-update")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCleanUpAfterUpdate() {
|
public function testCleanUpAfterUpdate() {
|
||||||
Phake::when(Arsse::$db)->articleCleanup()->thenReturn(true);
|
Phake::when(Arsse::$db)->articleCleanup()->thenReturn(true);
|
||||||
$exp = new Response(204);
|
$exp = new Response(204);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/after-update")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/cleanup/after-update")));
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use JKingWeb\Arsse\REST\Request;
|
use JKingWeb\Arsse\REST\Request;
|
||||||
use JKingWeb\Arsse\REST\Response;
|
use JKingWeb\Arsse\REST\Response;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\REST\NextCloudNews\Versions */
|
/** @covers \JKingWeb\Arsse\REST\NextCloudNews\Versions */
|
||||||
class TestNCNVersionDiscovery extends Test\AbstractTest {
|
class TestNCNVersionDiscovery extends Test\AbstractTest {
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchVersionList() {
|
public function testFetchVersionList() {
|
||||||
$exp = new Response(200, ['apiLevels' => ['v1-2']]);
|
$exp = new Response(200, ['apiLevels' => ['v1-2']]);
|
||||||
$h = new REST\NextCloudNews\Versions();
|
$h = new REST\NextCloudNews\Versions();
|
||||||
$req = new Request("GET", "/");
|
$req = new Request("GET", "/");
|
||||||
|
@ -24,7 +25,7 @@ class TestNCNVersionDiscovery extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $res);
|
$this->assertEquals($exp, $res);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUseIncorrectMethod() {
|
public function testUseIncorrectMethod() {
|
||||||
$exp = new Response(405);
|
$exp = new Response(405);
|
||||||
$h = new REST\NextCloudNews\Versions();
|
$h = new REST\NextCloudNews\Versions();
|
||||||
$req = new Request("POST", "/");
|
$req = new Request("POST", "/");
|
||||||
|
@ -32,7 +33,7 @@ class TestNCNVersionDiscovery extends Test\AbstractTest {
|
||||||
$this->assertEquals($exp, $res);
|
$this->assertEquals($exp, $res);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUseIncorrectPath() {
|
public function testUseIncorrectPath() {
|
||||||
$exp = new Response(501);
|
$exp = new Response(501);
|
||||||
$h = new REST\NextCloudNews\Versions();
|
$h = new REST\NextCloudNews\Versions();
|
||||||
$req = new Request("GET", "/ook");
|
$req = new Request("GET", "/ook");
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
|
||||||
|
@ -8,14 +9,14 @@ use Phake;
|
||||||
class TestService extends Test\AbstractTest {
|
class TestService extends Test\AbstractTest {
|
||||||
protected $srv;
|
protected $srv;
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
Arsse::$conf = new Conf();
|
Arsse::$conf = new Conf();
|
||||||
Arsse::$db = Phake::mock(Database::class);
|
Arsse::$db = Phake::mock(Database::class);
|
||||||
$this->srv = new Service();
|
$this->srv = new Service();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testComputeInterval() {
|
public function testComputeInterval() {
|
||||||
$in = [
|
$in = [
|
||||||
Arsse::$conf->serviceFrequency,
|
Arsse::$conf->serviceFrequency,
|
||||||
"PT2M",
|
"PT2M",
|
||||||
|
@ -25,20 +26,24 @@ class TestService extends Test\AbstractTest {
|
||||||
"interval",
|
"interval",
|
||||||
];
|
];
|
||||||
foreach ($in as $index => $spec) {
|
foreach ($in as $index => $spec) {
|
||||||
try{$exp = new \DateInterval($spec);} catch(\Exception $e) {$exp = new \DateInterval("PT2M");}
|
try {
|
||||||
|
$exp = new \DateInterval($spec);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$exp = new \DateInterval("PT2M");
|
||||||
|
}
|
||||||
Arsse::$conf->serviceFrequency = $spec;
|
Arsse::$conf->serviceFrequency = $spec;
|
||||||
$this->assertEquals($exp, Service::interval(), "Interval #$index '$spec' was not correctly calculated");
|
$this->assertEquals($exp, Service::interval(), "Interval #$index '$spec' was not correctly calculated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCheckIn() {
|
public function testCheckIn() {
|
||||||
$now = time();
|
$now = time();
|
||||||
$this->srv->checkIn();
|
$this->srv->checkIn();
|
||||||
Phake::verify(Arsse::$db)->metaSet("service_last_checkin", Phake::capture($then), "datetime");
|
Phake::verify(Arsse::$db)->metaSet("service_last_checkin", Phake::capture($then), "datetime");
|
||||||
$this->assertTime($now, $then);
|
$this->assertTime($now, $then);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testReportHavingCheckedIn() {
|
public function testReportHavingCheckedIn() {
|
||||||
// the mock's metaGet() returns null by default
|
// the mock's metaGet() returns null by default
|
||||||
$this->assertFalse(Service::hasCheckedIn());
|
$this->assertFalse(Service::hasCheckedIn());
|
||||||
$interval = Service::interval();
|
$interval = Service::interval();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
use Phake;
|
use Phake;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\User */
|
/** @covers \JKingWeb\Arsse\User */
|
||||||
|
@ -44,7 +45,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
|
|
||||||
protected $data;
|
protected $data;
|
||||||
|
|
||||||
function setUp(string $drv = Test\User\DriverInternalMock::class, string $db = null) {
|
public function setUp(string $drv = Test\User\DriverInternalMock::class, string $db = null) {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->userDriver = $drv;
|
$conf->userDriver = $drv;
|
||||||
|
@ -62,11 +63,11 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
Phake::reset(Arsse::$user);
|
Phake::reset(Arsse::$user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testToggleLogic() {
|
public function testToggleLogic() {
|
||||||
$this->assertTrue(Arsse::$user->authorizationEnabled());
|
$this->assertTrue(Arsse::$user->authorizationEnabled());
|
||||||
$this->assertTrue(Arsse::$user->authorizationEnabled(true));
|
$this->assertTrue(Arsse::$user->authorizationEnabled(true));
|
||||||
$this->assertFalse(Arsse::$user->authorizationEnabled(false));
|
$this->assertFalse(Arsse::$user->authorizationEnabled(false));
|
||||||
|
@ -75,7 +76,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
$this->assertTrue(Arsse::$user->authorizationEnabled(true));
|
$this->assertTrue(Arsse::$user->authorizationEnabled(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSelfActionLogic() {
|
public function testSelfActionLogic() {
|
||||||
foreach (array_keys(self::USERS) as $user) {
|
foreach (array_keys(self::USERS) as $user) {
|
||||||
Arsse::$user->auth($user, "");
|
Arsse::$user->auth($user, "");
|
||||||
// users should be able to do basic actions for themselves
|
// users should be able to do basic actions for themselves
|
||||||
|
@ -84,7 +85,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRegularUserLogic() {
|
public function testRegularUserLogic() {
|
||||||
foreach (self::USERS as $actor => $rights) {
|
foreach (self::USERS as $actor => $rights) {
|
||||||
if ($rights != User\Driver::RIGHTS_NONE) {
|
if ($rights != User\Driver::RIGHTS_NONE) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -111,7 +112,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDomainManagerLogic() {
|
public function testDomainManagerLogic() {
|
||||||
foreach (self::USERS as $actor => $actorRights) {
|
foreach (self::USERS as $actor => $actorRights) {
|
||||||
if ($actorRights != User\Driver::RIGHTS_DOMAIN_MANAGER) {
|
if ($actorRights != User\Driver::RIGHTS_DOMAIN_MANAGER) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -152,7 +153,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDomainAdministratorLogic() {
|
public function testDomainAdministratorLogic() {
|
||||||
foreach (self::USERS as $actor => $actorRights) {
|
foreach (self::USERS as $actor => $actorRights) {
|
||||||
if ($actorRights != User\Driver::RIGHTS_DOMAIN_ADMIN) {
|
if ($actorRights != User\Driver::RIGHTS_DOMAIN_ADMIN) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -194,7 +195,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGlobalManagerLogic() {
|
public function testGlobalManagerLogic() {
|
||||||
foreach (self::USERS as $actor => $actorRights) {
|
foreach (self::USERS as $actor => $actorRights) {
|
||||||
if ($actorRights != User\Driver::RIGHTS_GLOBAL_MANAGER) {
|
if ($actorRights != User\Driver::RIGHTS_GLOBAL_MANAGER) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -227,7 +228,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGlobalAdministratorLogic() {
|
public function testGlobalAdministratorLogic() {
|
||||||
foreach (self::USERS as $actor => $actorRights) {
|
foreach (self::USERS as $actor => $actorRights) {
|
||||||
if ($actorRights != User\Driver::RIGHTS_GLOBAL_ADMIN) {
|
if ($actorRights != User\Driver::RIGHTS_GLOBAL_ADMIN) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -247,7 +248,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInvalidLevelLogic() {
|
public function testInvalidLevelLogic() {
|
||||||
foreach (self::USERS as $actor => $rights) {
|
foreach (self::USERS as $actor => $rights) {
|
||||||
if (in_array($rights, self::LEVELS)) {
|
if (in_array($rights, self::LEVELS)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -274,7 +275,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInternalExceptionLogic() {
|
public function testInternalExceptionLogic() {
|
||||||
$tests = [
|
$tests = [
|
||||||
// methods of User class to test, with parameters besides affected user
|
// methods of User class to test, with parameters besides affected user
|
||||||
'exists' => [],
|
'exists' => [],
|
||||||
|
@ -295,7 +296,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
$this->assertCount(sizeof($tests), $this->checkExceptions("user@example.org", $tests));
|
$this->assertCount(sizeof($tests), $this->checkExceptions("user@example.org", $tests));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExternalExceptionLogic() {
|
public function testExternalExceptionLogic() {
|
||||||
// set up the test for an external driver
|
// set up the test for an external driver
|
||||||
$this->setUp(Test\User\DriverExternalMock::class, Test\User\Database::class);
|
$this->setUp(Test\User\DriverExternalMock::class, Test\User\Database::class);
|
||||||
// run the previous test with the external driver set up
|
// run the previous test with the external driver set up
|
||||||
|
@ -320,7 +321,7 @@ class TestAuthorization extends Test\AbstractTest {
|
||||||
return $err;
|
return $err;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMissingUserLogic() {
|
public function testMissingUserLogic() {
|
||||||
Arsse::$user->auth("gadm@example.com", "");
|
Arsse::$user->auth("gadm@example.com", "");
|
||||||
$this->assertTrue(Arsse::$user->authorize("user@example.com", "someFunction"));
|
$this->assertTrue(Arsse::$user->authorize("user@example.com", "someFunction"));
|
||||||
$this->assertException("doesNotExist", "User");
|
$this->assertException("doesNotExist", "User");
|
||||||
|
|
|
@ -11,7 +11,7 @@ class TestUserMockInternal extends Test\AbstractTest {
|
||||||
|
|
||||||
public $drv = Test\User\DriverInternalMock::class;
|
public $drv = Test\User\DriverInternalMock::class;
|
||||||
|
|
||||||
function setUpSeries() {
|
public function setUpSeries() {
|
||||||
Arsse::$db = null;
|
Arsse::$db = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test;
|
namespace JKingWeb\Arsse\Test;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Exception;
|
use JKingWeb\Arsse\Exception;
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
|
|
||||||
/** @coversNothing */
|
/** @coversNothing */
|
||||||
abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
public function assertException(string $msg = "", string $prefix = "", string $type = "Exception") {
|
||||||
function assertException(string $msg = "", string $prefix = "", string $type = "Exception") {
|
|
||||||
if (func_num_args()) {
|
if (func_num_args()) {
|
||||||
$class = \JKingWeb\Arsse\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type;
|
$class = \JKingWeb\Arsse\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type;
|
||||||
$msgID = ($prefix !== "" ? $prefix . "/" : "") . $type. ".$msg";
|
$msgID = ($prefix !== "" ? $prefix . "/" : "") . $type. ".$msg";
|
||||||
|
@ -25,13 +25,13 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertTime($exp, $test) {
|
public function assertTime($exp, $test) {
|
||||||
$exp = Date::transform($exp, "iso8601");
|
$exp = Date::transform($exp, "iso8601");
|
||||||
$test = Date::transform($test, "iso8601");
|
$test = Date::transform($test, "iso8601");
|
||||||
$this->assertSame($exp, $test);
|
$this->assertSame($exp, $test);
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearData(bool $loadLang = true): bool {
|
public function clearData(bool $loadLang = true): bool {
|
||||||
$r = new \ReflectionClass(\JKingWeb\Arsse\Arsse::class);
|
$r = new \ReflectionClass(\JKingWeb\Arsse\Arsse::class);
|
||||||
$props = array_keys($r->getStaticProperties());
|
$props = array_keys($r->getStaticProperties());
|
||||||
foreach ($props as $prop) {
|
foreach ($props as $prop) {
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Db\SQLite3\Driver;
|
use JKingWeb\Arsse\Db\SQLite3\Driver;
|
||||||
|
|
||||||
trait DriverSQLite3 {
|
trait DriverSQLite3 {
|
||||||
function setUpDriver() {
|
public function setUpDriver() {
|
||||||
if (!extension_loaded("sqlite3")) {
|
if (!extension_loaded("sqlite3")) {
|
||||||
$this->markTestSkipped("SQLite extension not loaded");
|
$this->markTestSkipped("SQLite extension not loaded");
|
||||||
}
|
}
|
||||||
|
@ -13,7 +14,7 @@ trait DriverSQLite3 {
|
||||||
$this->drv = new Driver(true);
|
$this->drv = new Driver(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextID(string $table): int {
|
public function nextID(string $table): int {
|
||||||
return $this->drv->query("SELECT (case when max(id) then max(id) else 0 end)+1 from $table")->getValue();
|
return $this->drv->query("SELECT (case when max(id) then max(id) else 0 end)+1 from $table")->getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Misc\Context;
|
use JKingWeb\Arsse\Misc\Context;
|
||||||
use JKingWeb\Arsse\Misc\Date;
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
|
@ -299,7 +300,7 @@ trait SeriesArticle {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
function setUpSeries() {
|
public function setUpSeries() {
|
||||||
$this->checkTables = ['arsse_marks' => ["subscription","article","read","starred","modified"],];
|
$this->checkTables = ['arsse_marks' => ["subscription","article","read","starred","modified"],];
|
||||||
$this->user = "john.doe@example.net";
|
$this->user = "john.doe@example.net";
|
||||||
}
|
}
|
||||||
|
@ -311,7 +312,7 @@ trait SeriesArticle {
|
||||||
$this->assertEquals($exp, $ids);
|
$this->assertEquals($exp, $ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListArticlesCheckingContext() {
|
public function testListArticlesCheckingContext() {
|
||||||
$this->user = "john.doe@example.com";
|
$this->user = "john.doe@example.com";
|
||||||
// get all items for user
|
// get all items for user
|
||||||
$exp = [1,2,3,4,5,6,7,8,19,20];
|
$exp = [1,2,3,4,5,6,7,8,19,20];
|
||||||
|
@ -356,28 +357,28 @@ trait SeriesArticle {
|
||||||
$this->compareIds([7,6], (new Context)->reverse(true)->limit(2)->latestEdition(8-1));
|
$this->compareIds([7,6], (new Context)->reverse(true)->limit(2)->latestEdition(8-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListArticlesOfAMissingFolder() {
|
public function testListArticlesOfAMissingFolder() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->articleList($this->user, (new Context)->folder(1));
|
Arsse::$db->articleList($this->user, (new Context)->folder(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListArticlesOfAMissingSubscription() {
|
public function testListArticlesOfAMissingSubscription() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->articleList($this->user, (new Context)->subscription(1));
|
Arsse::$db->articleList($this->user, (new Context)->subscription(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListArticlesCheckingProperties() {
|
public function testListArticlesCheckingProperties() {
|
||||||
$this->user = "john.doe@example.org";
|
$this->user = "john.doe@example.org";
|
||||||
$this->assertResult($this->matches, Arsse::$db->articleList($this->user));
|
$this->assertResult($this->matches, Arsse::$db->articleList($this->user));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListArticlesWithoutAuthority() {
|
public function testListArticlesWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->articleList($this->user);
|
Arsse::$db->articleList($this->user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAllArticlesUnread() {
|
public function testMarkAllArticlesUnread() {
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false]);
|
Arsse::$db->articleMark($this->user, ['read'=>false]);
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -388,7 +389,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAllArticlesRead() {
|
public function testMarkAllArticlesRead() {
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>true]);
|
Arsse::$db->articleMark($this->user, ['read'=>true]);
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -403,7 +404,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAllArticlesUnstarred() {
|
public function testMarkAllArticlesUnstarred() {
|
||||||
Arsse::$db->articleMark($this->user, ['starred'=>false]);
|
Arsse::$db->articleMark($this->user, ['starred'=>false]);
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -414,7 +415,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAllArticlesStarred() {
|
public function testMarkAllArticlesStarred() {
|
||||||
Arsse::$db->articleMark($this->user, ['starred'=>true]);
|
Arsse::$db->articleMark($this->user, ['starred'=>true]);
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -429,7 +430,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAllArticlesUnreadAndUnstarred() {
|
public function testMarkAllArticlesUnreadAndUnstarred() {
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>false]);
|
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>false]);
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -443,7 +444,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAllArticlesReadAndStarred() {
|
public function testMarkAllArticlesReadAndStarred() {
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>true,'starred'=>true]);
|
Arsse::$db->articleMark($this->user, ['read'=>true,'starred'=>true]);
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -461,7 +462,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAllArticlesUnreadAndStarred() {
|
public function testMarkAllArticlesUnreadAndStarred() {
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true]);
|
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true]);
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -479,7 +480,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAllArticlesReadAndUnstarred() {
|
public function testMarkAllArticlesReadAndUnstarred() {
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>true,'starred'=>false]);
|
Arsse::$db->articleMark($this->user, ['read'=>true,'starred'=>false]);
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -497,7 +498,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkATreeFolder() {
|
public function testMarkATreeFolder() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -508,7 +509,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkALeafFolder() {
|
public function testMarkALeafFolder() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -517,12 +518,12 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAMissingFolder() {
|
public function testMarkAMissingFolder() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$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));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkASubscription() {
|
public function testMarkASubscription() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -531,12 +532,12 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAMissingSubscription() {
|
public function testMarkAMissingSubscription() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$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));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAnArticle() {
|
public function testMarkAnArticle() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -545,7 +546,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkMultipleArticles() {
|
public function testMarkMultipleArticles() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -555,7 +556,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkMultipleArticlessUnreadAndStarred() {
|
public function testMarkMultipleArticlessUnreadAndStarred() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -568,22 +569,22 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkTooFewMultipleArticles() {
|
public function testMarkTooFewMultipleArticles() {
|
||||||
$this->assertException("tooShort", "Db", "ExceptionInput");
|
$this->assertException("tooShort", "Db", "ExceptionInput");
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles([]));
|
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkTooManyMultipleArticles() {
|
public function testMarkTooManyMultipleArticles() {
|
||||||
$this->assertException("tooLong", "Db", "ExceptionInput");
|
$this->assertException("tooLong", "Db", "ExceptionInput");
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles(range(1, 51)));
|
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->articles(range(1, 51)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAMissingArticle() {
|
public function testMarkAMissingArticle() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$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));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAnEdition() {
|
public function testMarkAnEdition() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -592,7 +593,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkMultipleEditions() {
|
public function testMarkMultipleEditions() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -602,7 +603,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkMultipleEditionsUnread() {
|
public function testMarkMultipleEditionsUnread() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -613,7 +614,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkMultipleEditionsUnreadWithStale() {
|
public function testMarkMultipleEditionsUnreadWithStale() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -622,7 +623,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkMultipleEditionsUnreadAndStarredWithStale() {
|
public function testMarkMultipleEditionsUnreadAndStarredWithStale() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -634,23 +635,23 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkTooFewMultipleEditions() {
|
public function testMarkTooFewMultipleEditions() {
|
||||||
$this->assertException("tooShort", "Db", "ExceptionInput");
|
$this->assertException("tooShort", "Db", "ExceptionInput");
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions([]));
|
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkTooManyMultipleEditions() {
|
public function testMarkTooManyMultipleEditions() {
|
||||||
$this->assertException("tooLong", "Db", "ExceptionInput");
|
$this->assertException("tooLong", "Db", "ExceptionInput");
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions(range(1, 51)));
|
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->editions(range(1, 51)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAStaleEditionUnread() {
|
public function testMarkAStaleEditionUnread() {
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false], (new Context)->edition(20)); // no changes occur
|
Arsse::$db->articleMark($this->user, ['read'=>false], (new Context)->edition(20)); // no changes occur
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAStaleEditionStarred() {
|
public function testMarkAStaleEditionStarred() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -659,7 +660,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAStaleEditionUnreadAndStarred() {
|
public function testMarkAStaleEditionUnreadAndStarred() {
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->edition(20)); // only starred is changed
|
Arsse::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->edition(20)); // only starred is changed
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -668,18 +669,18 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAStaleEditionUnreadAndUnstarred() {
|
public function testMarkAStaleEditionUnreadAndUnstarred() {
|
||||||
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);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkAMissingEdition() {
|
public function testMarkAMissingEdition() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$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));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkByOldestEdition() {
|
public function testMarkByOldestEdition() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -690,7 +691,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkByLatestEdition() {
|
public function testMarkByLatestEdition() {
|
||||||
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");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -703,7 +704,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkByLastModified() {
|
public function testMarkByLastModified() {
|
||||||
Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->modifiedSince('2017-01-01T00:00:00Z'));
|
Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->modifiedSince('2017-01-01T00:00:00Z'));
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -714,7 +715,7 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkByNotLastModified() {
|
public function testMarkByNotLastModified() {
|
||||||
Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->notModifiedSince('2000-01-01T00:00:00Z'));
|
Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->notModifiedSince('2000-01-01T00:00:00Z'));
|
||||||
$now = Date::transform(time(), "sql");
|
$now = Date::transform(time(), "sql");
|
||||||
$state = $this->primeExpectations($this->data, $this->checkTables);
|
$state = $this->primeExpectations($this->data, $this->checkTables);
|
||||||
|
@ -723,36 +724,36 @@ trait SeriesArticle {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMarkArticlesWithoutAuthority() {
|
public function testMarkArticlesWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->articleMark($this->user, ['read'=>false]);
|
Arsse::$db->articleMark($this->user, ['read'=>false]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCountStarredArticles() {
|
public function testCountStarredArticles() {
|
||||||
$this->assertSame(2, Arsse::$db->articleStarredCount("john.doe@example.com"));
|
$this->assertSame(2, Arsse::$db->articleStarredCount("john.doe@example.com"));
|
||||||
$this->assertSame(2, Arsse::$db->articleStarredCount("john.doe@example.org"));
|
$this->assertSame(2, Arsse::$db->articleStarredCount("john.doe@example.org"));
|
||||||
$this->assertSame(2, Arsse::$db->articleStarredCount("john.doe@example.net"));
|
$this->assertSame(2, Arsse::$db->articleStarredCount("john.doe@example.net"));
|
||||||
$this->assertSame(0, Arsse::$db->articleStarredCount("jane.doe@example.com"));
|
$this->assertSame(0, Arsse::$db->articleStarredCount("jane.doe@example.com"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCountStarredArticlesWithoutAuthority() {
|
public function testCountStarredArticlesWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->articleStarredCount($this->user);
|
Arsse::$db->articleStarredCount($this->user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchLatestEdition() {
|
public function testFetchLatestEdition() {
|
||||||
$this->assertSame(1001, Arsse::$db->editionLatest($this->user));
|
$this->assertSame(1001, Arsse::$db->editionLatest($this->user));
|
||||||
$this->assertSame(4, Arsse::$db->editionLatest($this->user, (new Context)->subscription(12)));
|
$this->assertSame(4, Arsse::$db->editionLatest($this->user, (new Context)->subscription(12)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchLatestEditionOfMissingSubscription() {
|
public function testFetchLatestEditionOfMissingSubscription() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->editionLatest($this->user, (new Context)->subscription(1));
|
Arsse::$db->editionLatest($this->user, (new Context)->subscription(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchLatestEditionWithoutAuthority() {
|
public function testFetchLatestEditionWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->editionLatest($this->user);
|
Arsse::$db->editionLatest($this->user);
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
|
||||||
trait SeriesCleanup {
|
trait SeriesCleanup {
|
||||||
|
public function setUpSeries() {
|
||||||
function setUpSeries() {
|
|
||||||
// set up the test data
|
// 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"));
|
$yesterday = gmdate("Y-m-d H:i:s", strtotime("now - 1 day"));
|
||||||
|
@ -109,7 +109,7 @@ trait SeriesCleanup {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCleanUpOrphanedFeeds() {
|
public function testCleanUpOrphanedFeeds() {
|
||||||
Arsse::$db->feedCleanup();
|
Arsse::$db->feedCleanup();
|
||||||
$now = gmdate("Y-m-d H:i:s");
|
$now = gmdate("Y-m-d H:i:s");
|
||||||
$state = $this->primeExpectations($this->data, [
|
$state = $this->primeExpectations($this->data, [
|
||||||
|
@ -121,7 +121,7 @@ trait SeriesCleanup {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCleanUpOldArticlesWithStandardRetention() {
|
public function testCleanUpOldArticlesWithStandardRetention() {
|
||||||
Arsse::$db->articleCleanup();
|
Arsse::$db->articleCleanup();
|
||||||
$state = $this->primeExpectations($this->data, [
|
$state = $this->primeExpectations($this->data, [
|
||||||
'arsse_articles' => ["id"]
|
'arsse_articles' => ["id"]
|
||||||
|
@ -132,7 +132,7 @@ trait SeriesCleanup {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCleanUpOldArticlesWithUnlimitedReadRetention() {
|
public function testCleanUpOldArticlesWithUnlimitedReadRetention() {
|
||||||
Arsse::$conf->purgeArticlesRead = "";
|
Arsse::$conf->purgeArticlesRead = "";
|
||||||
Arsse::$db->articleCleanup();
|
Arsse::$db->articleCleanup();
|
||||||
$state = $this->primeExpectations($this->data, [
|
$state = $this->primeExpectations($this->data, [
|
||||||
|
@ -144,7 +144,7 @@ trait SeriesCleanup {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCleanUpOldArticlesWithUnlimitedUnreadRetention() {
|
public function testCleanUpOldArticlesWithUnlimitedUnreadRetention() {
|
||||||
Arsse::$conf->purgeArticlesUnread = "";
|
Arsse::$conf->purgeArticlesUnread = "";
|
||||||
Arsse::$db->articleCleanup();
|
Arsse::$db->articleCleanup();
|
||||||
$state = $this->primeExpectations($this->data, [
|
$state = $this->primeExpectations($this->data, [
|
||||||
|
@ -156,7 +156,7 @@ trait SeriesCleanup {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCleanUpOldArticlesWithUnlimitedRetention() {
|
public function testCleanUpOldArticlesWithUnlimitedRetention() {
|
||||||
Arsse::$conf->purgeArticlesRead = "";
|
Arsse::$conf->purgeArticlesRead = "";
|
||||||
Arsse::$conf->purgeArticlesUnread = "";
|
Arsse::$conf->purgeArticlesUnread = "";
|
||||||
Arsse::$db->articleCleanup();
|
Arsse::$db->articleCleanup();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Feed;
|
use JKingWeb\Arsse\Feed;
|
||||||
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
||||||
|
@ -26,7 +27,7 @@ trait SeriesFeed {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
function setUpSeries() {
|
public function setUpSeries() {
|
||||||
// set up the test data
|
// 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"));
|
$future = gmdate("Y-m-d H:i:s", strtotime("now + 1 minute"));
|
||||||
|
@ -160,11 +161,11 @@ trait SeriesFeed {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListLatestItems() {
|
public function testListLatestItems() {
|
||||||
$this->assertResult($this->matches, Arsse::$db->feedMatchLatest(1, 2));
|
$this->assertResult($this->matches, Arsse::$db->feedMatchLatest(1, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMatchItemsById() {
|
public function testMatchItemsById() {
|
||||||
$this->assertResult($this->matches, Arsse::$db->feedMatchIds(1, ['804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41']));
|
$this->assertResult($this->matches, Arsse::$db->feedMatchIds(1, ['804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41']));
|
||||||
foreach ($this->matches as $m) {
|
foreach ($this->matches as $m) {
|
||||||
$exp = [$m];
|
$exp = [$m];
|
||||||
|
@ -175,7 +176,7 @@ trait SeriesFeed {
|
||||||
$this->assertResult([['id' => 1]], Arsse::$db->feedMatchIds(1, ['e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda'])); // this ID appears in both feed 1 and feed 2; only one result should be returned
|
$this->assertResult([['id' => 1]], Arsse::$db->feedMatchIds(1, ['e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda'])); // this ID appears in both feed 1 and feed 2; only one result should be returned
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUpdateAFeed() {
|
public function testUpdateAFeed() {
|
||||||
// update a valid feed with both new and changed items
|
// update a valid feed with both new and changed items
|
||||||
Arsse::$db->feedUpdate(1);
|
Arsse::$db->feedUpdate(1);
|
||||||
$now = gmdate("Y-m-d H:i:s");
|
$now = gmdate("Y-m-d H:i:s");
|
||||||
|
@ -215,17 +216,17 @@ trait SeriesFeed {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUpdateAMissingFeed() {
|
public function testUpdateAMissingFeed() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->feedUpdate(2112);
|
Arsse::$db->feedUpdate(2112);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUpdateAFeedThrowingExceptions() {
|
public function testUpdateAFeedThrowingExceptions() {
|
||||||
$this->assertException("invalidUrl", "Feed");
|
$this->assertException("invalidUrl", "Feed");
|
||||||
Arsse::$db->feedUpdate(3, true);
|
Arsse::$db->feedUpdate(3, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUpdateAFeedWithEnclosuresAndCategories() {
|
public function testUpdateAFeedWithEnclosuresAndCategories() {
|
||||||
Arsse::$db->feedUpdate(5);
|
Arsse::$db->feedUpdate(5);
|
||||||
$state = $this->primeExpectations($this->data, [
|
$state = $this->primeExpectations($this->data, [
|
||||||
'arsse_enclosures' => ["url","type"],
|
'arsse_enclosures' => ["url","type"],
|
||||||
|
@ -245,7 +246,7 @@ trait SeriesFeed {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListStaleFeeds() {
|
public function testListStaleFeeds() {
|
||||||
$this->assertSame([1,3,4], Arsse::$db->feedListStale());
|
$this->assertSame([1,3,4], Arsse::$db->feedListStale());
|
||||||
Arsse::$db->feedUpdate(3);
|
Arsse::$db->feedUpdate(3);
|
||||||
Arsse::$db->feedUpdate(4);
|
Arsse::$db->feedUpdate(4);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ trait SeriesFolder {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
function testAddARootFolder() {
|
public function testAddARootFolder() {
|
||||||
$user = "john.doe@example.com";
|
$user = "john.doe@example.com";
|
||||||
$folderID = $this->nextID("arsse_folders");
|
$folderID = $this->nextID("arsse_folders");
|
||||||
$this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "Entertainment"]));
|
$this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "Entertainment"]));
|
||||||
|
@ -55,12 +56,12 @@ trait SeriesFolder {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddADuplicateRootFolder() {
|
public function testAddADuplicateRootFolder() {
|
||||||
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Politics"]);
|
Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Politics"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddANestedFolder() {
|
public function testAddANestedFolder() {
|
||||||
$user = "john.doe@example.com";
|
$user = "john.doe@example.com";
|
||||||
$folderID = $this->nextID("arsse_folders");
|
$folderID = $this->nextID("arsse_folders");
|
||||||
$this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "GNOME", 'parent' => 2]));
|
$this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "GNOME", 'parent' => 2]));
|
||||||
|
@ -70,38 +71,38 @@ trait SeriesFolder {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddANestedFolderToAMissingParent() {
|
public function testAddANestedFolderToAMissingParent() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology", 'parent' => 2112]);
|
Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology", 'parent' => 2112]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddANestedFolderForTheWrongOwner() {
|
public function testAddANestedFolderForTheWrongOwner() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology", 'parent' => 4]); // folder ID 4 belongs to Jane
|
Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology", 'parent' => 4]); // folder ID 4 belongs to Jane
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddAFolderWithAMissingName() {
|
public function testAddAFolderWithAMissingName() {
|
||||||
$this->assertException("missing", "Db", "ExceptionInput");
|
$this->assertException("missing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderAdd("john.doe@example.com", []);
|
Arsse::$db->folderAdd("john.doe@example.com", []);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddAFolderWithABlankName() {
|
public function testAddAFolderWithABlankName() {
|
||||||
$this->assertException("missing", "Db", "ExceptionInput");
|
$this->assertException("missing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderAdd("john.doe@example.com", ['name' => ""]);
|
Arsse::$db->folderAdd("john.doe@example.com", ['name' => ""]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddAFolderWithAWhitespaceName() {
|
public function testAddAFolderWithAWhitespaceName() {
|
||||||
$this->assertException("whitespace", "Db", "ExceptionInput");
|
$this->assertException("whitespace", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderAdd("john.doe@example.com", ['name' => " "]);
|
Arsse::$db->folderAdd("john.doe@example.com", ['name' => " "]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddAFolderWithoutAuthority() {
|
public function testAddAFolderWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology"]);
|
Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListRootFolders() {
|
public function testListRootFolders() {
|
||||||
$exp = [
|
$exp = [
|
||||||
['id' => 5, 'name' => "Politics", 'parent' => null],
|
['id' => 5, 'name' => "Politics", 'parent' => null],
|
||||||
['id' => 1, 'name' => "Technology", 'parent' => null],
|
['id' => 1, 'name' => "Technology", 'parent' => null],
|
||||||
|
@ -118,7 +119,7 @@ trait SeriesFolder {
|
||||||
Phake::verify(Arsse::$user)->authorize("admin@example.net", "folderList");
|
Phake::verify(Arsse::$user)->authorize("admin@example.net", "folderList");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListFoldersRecursively() {
|
public function testListFoldersRecursively() {
|
||||||
$exp = [
|
$exp = [
|
||||||
['id' => 5, 'name' => "Politics", 'parent' => null],
|
['id' => 5, 'name' => "Politics", 'parent' => null],
|
||||||
['id' => 6, 'name' => "Politics", 'parent' => 2],
|
['id' => 6, 'name' => "Politics", 'parent' => 2],
|
||||||
|
@ -139,23 +140,23 @@ trait SeriesFolder {
|
||||||
Phake::verify(Arsse::$user)->authorize("jane.doe@example.com", "folderList");
|
Phake::verify(Arsse::$user)->authorize("jane.doe@example.com", "folderList");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListFoldersOfAMissingParent() {
|
public function testListFoldersOfAMissingParent() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderList("john.doe@example.com", 2112);
|
Arsse::$db->folderList("john.doe@example.com", 2112);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListFoldersOfTheWrongOwner() {
|
public function testListFoldersOfTheWrongOwner() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderList("john.doe@example.com", 4); // folder ID 4 belongs to Jane
|
Arsse::$db->folderList("john.doe@example.com", 4); // folder ID 4 belongs to Jane
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListFoldersWithoutAuthority() {
|
public function testListFoldersWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->folderList("john.doe@example.com");
|
Arsse::$db->folderList("john.doe@example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAFolder() {
|
public function testRemoveAFolder() {
|
||||||
$this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 6));
|
$this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 6));
|
||||||
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderRemove");
|
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderRemove");
|
||||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||||
|
@ -163,7 +164,7 @@ trait SeriesFolder {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAFolderTree() {
|
public function testRemoveAFolderTree() {
|
||||||
$this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 1));
|
$this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 1));
|
||||||
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderRemove");
|
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderRemove");
|
||||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||||
|
@ -173,23 +174,23 @@ trait SeriesFolder {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAMissingFolder() {
|
public function testRemoveAMissingFolder() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderRemove("john.doe@example.com", 2112);
|
Arsse::$db->folderRemove("john.doe@example.com", 2112);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAFolderOfTheWrongOwner() {
|
public function testRemoveAFolderOfTheWrongOwner() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderRemove("john.doe@example.com", 4); // folder ID 4 belongs to Jane
|
Arsse::$db->folderRemove("john.doe@example.com", 4); // folder ID 4 belongs to Jane
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAFolderWithoutAuthority() {
|
public function testRemoveAFolderWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->folderRemove("john.doe@example.com", 1);
|
Arsse::$db->folderRemove("john.doe@example.com", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetThePropertiesOfAFolder() {
|
public function testGetThePropertiesOfAFolder() {
|
||||||
$exp = [
|
$exp = [
|
||||||
'id' => 6,
|
'id' => 6,
|
||||||
'name' => "Politics",
|
'name' => "Politics",
|
||||||
|
@ -199,23 +200,23 @@ trait SeriesFolder {
|
||||||
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesGet");
|
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesGet");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetThePropertiesOfAMissingFolder() {
|
public function testGetThePropertiesOfAMissingFolder() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderPropertiesGet("john.doe@example.com", 2112);
|
Arsse::$db->folderPropertiesGet("john.doe@example.com", 2112);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetThePropertiesOfAFolderOfTheWrongOwner() {
|
public function testGetThePropertiesOfAFolderOfTheWrongOwner() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderPropertiesGet("john.doe@example.com", 4); // folder ID 4 belongs to Jane
|
Arsse::$db->folderPropertiesGet("john.doe@example.com", 4); // folder ID 4 belongs to Jane
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetThePropertiesOfAFolderWithoutAuthority() {
|
public function testGetThePropertiesOfAFolderWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->folderPropertiesGet("john.doe@example.com", 1);
|
Arsse::$db->folderPropertiesGet("john.doe@example.com", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameAFolder() {
|
public function testRenameAFolder() {
|
||||||
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => "Opinion"]));
|
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => "Opinion"]));
|
||||||
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesSet");
|
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesSet");
|
||||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||||
|
@ -223,17 +224,17 @@ trait SeriesFolder {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameAFolderToTheEmptyString() {
|
public function testRenameAFolderToTheEmptyString() {
|
||||||
$this->assertException("missing", "Db", "ExceptionInput");
|
$this->assertException("missing", "Db", "ExceptionInput");
|
||||||
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => ""]));
|
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => ""]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameAFolderToWhitespaceOnly() {
|
public function testRenameAFolderToWhitespaceOnly() {
|
||||||
$this->assertException("whitespace", "Db", "ExceptionInput");
|
$this->assertException("whitespace", "Db", "ExceptionInput");
|
||||||
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => " "]));
|
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => " "]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMoveAFolder() {
|
public function testMoveAFolder() {
|
||||||
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => 5]));
|
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => 5]));
|
||||||
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesSet");
|
Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesSet");
|
||||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||||
|
@ -241,37 +242,37 @@ trait SeriesFolder {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMoveAFolderToItsDescendant() {
|
public function testMoveAFolderToItsDescendant() {
|
||||||
$this->assertException("circularDependence", "Db", "ExceptionInput");
|
$this->assertException("circularDependence", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 3]);
|
Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMoveAFolderToItself() {
|
public function testMoveAFolderToItself() {
|
||||||
$this->assertException("circularDependence", "Db", "ExceptionInput");
|
$this->assertException("circularDependence", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 1]);
|
Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMoveAFolderToAMissingParent() {
|
public function testMoveAFolderToAMissingParent() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 2112]);
|
Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 2112]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCauseAFolderCollision() {
|
public function testCauseAFolderCollision() {
|
||||||
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => null]);
|
Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => null]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetThePropertiesOfAMissingFolder() {
|
public function testSetThePropertiesOfAMissingFolder() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderPropertiesSet("john.doe@example.com", 2112, ['parent' => null]);
|
Arsse::$db->folderPropertiesSet("john.doe@example.com", 2112, ['parent' => null]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetThePropertiesOfAFolderForTheWrongOwner() {
|
public function testSetThePropertiesOfAFolderForTheWrongOwner() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->folderPropertiesSet("john.doe@example.com", 4, ['parent' => null]); // folder ID 4 belongs to Jane
|
Arsse::$db->folderPropertiesSet("john.doe@example.com", 4, ['parent' => null]); // folder ID 4 belongs to Jane
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetThePropertiesOfAFolderWithoutAuthority() {
|
public function testSetThePropertiesOfAFolderWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => null]);
|
Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => null]);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Test\Database;
|
use JKingWeb\Arsse\Test\Database;
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ trait SeriesMeta {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
function setUpSeries() {
|
public function setUpSeries() {
|
||||||
// the schema_version key is a special case, and to avoid jumping through hoops for every test we deal with it now
|
// the schema_version key is a special case, and to avoid jumping through hoops for every test we deal with it now
|
||||||
$this->data = $this->dataBare;
|
$this->data = $this->dataBare;
|
||||||
// as far as tests are concerned the schema version is part of the expectations primed into the database
|
// as far as tests are concerned the schema version is part of the expectations primed into the database
|
||||||
|
@ -27,14 +28,14 @@ trait SeriesMeta {
|
||||||
$this->primeDatabase($this->dataBare);
|
$this->primeDatabase($this->dataBare);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddANewValue() {
|
public function testAddANewValue() {
|
||||||
$this->assertTrue(Arsse::$db->metaSet("favourite", "Cygnus X-1"));
|
$this->assertTrue(Arsse::$db->metaSet("favourite", "Cygnus X-1"));
|
||||||
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
|
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
|
||||||
$state['arsse_meta']['rows'][] = ["favourite","Cygnus X-1"];
|
$state['arsse_meta']['rows'][] = ["favourite","Cygnus X-1"];
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddANewTypedValue() {
|
public function testAddANewTypedValue() {
|
||||||
$this->assertTrue(Arsse::$db->metaSet("answer", 42, "int"));
|
$this->assertTrue(Arsse::$db->metaSet("answer", 42, "int"));
|
||||||
$this->assertTrue(Arsse::$db->metaSet("true", true, "bool"));
|
$this->assertTrue(Arsse::$db->metaSet("true", true, "bool"));
|
||||||
$this->assertTrue(Arsse::$db->metaSet("false", false, "bool"));
|
$this->assertTrue(Arsse::$db->metaSet("false", false, "bool"));
|
||||||
|
@ -47,14 +48,14 @@ trait SeriesMeta {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testChangeAnExistingValue() {
|
public function testChangeAnExistingValue() {
|
||||||
$this->assertTrue(Arsse::$db->metaSet("album", "Hemispheres"));
|
$this->assertTrue(Arsse::$db->metaSet("album", "Hemispheres"));
|
||||||
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
|
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
|
||||||
$state['arsse_meta']['rows'][1][1] = "Hemispheres";
|
$state['arsse_meta']['rows'][1][1] = "Hemispheres";
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAValue() {
|
public function testRemoveAValue() {
|
||||||
$this->assertTrue(Arsse::$db->metaRemove("album"));
|
$this->assertTrue(Arsse::$db->metaRemove("album"));
|
||||||
$this->assertFalse(Arsse::$db->metaRemove("album"));
|
$this->assertFalse(Arsse::$db->metaRemove("album"));
|
||||||
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
|
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
|
||||||
|
@ -62,7 +63,7 @@ trait SeriesMeta {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRetrieveAValue() {
|
public function testRetrieveAValue() {
|
||||||
$this->assertSame("".Database::SCHEMA_VERSION, Arsse::$db->metaGet("schema_version"));
|
$this->assertSame("".Database::SCHEMA_VERSION, Arsse::$db->metaGet("schema_version"));
|
||||||
$this->assertSame("A Farewell to Kings", Arsse::$db->metaGet("album"));
|
$this->assertSame("A Farewell to Kings", Arsse::$db->metaGet("album"));
|
||||||
$this->assertSame(null, Arsse::$db->metaGet("this_key_does_not_exist"));
|
$this->assertSame(null, Arsse::$db->metaGet("this_key_does_not_exist"));
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Database;
|
use JKingWeb\Arsse\Database;
|
||||||
|
|
||||||
trait SeriesMiscellany {
|
trait SeriesMiscellany {
|
||||||
|
public function testListDrivers() {
|
||||||
function testListDrivers() {
|
|
||||||
$exp = [
|
$exp = [
|
||||||
'JKingWeb\\Arsse\\Db\\SQLite3\\Driver' => Arsse::$lang->msg("Driver.Db.SQLite3.Name"),
|
'JKingWeb\\Arsse\\Db\\SQLite3\\Driver' => Arsse::$lang->msg("Driver.Db.SQLite3.Name"),
|
||||||
];
|
];
|
||||||
$this->assertArraySubset($exp, Database::driverList());
|
$this->assertArraySubset($exp, Database::driverList());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInitializeDatabase() {
|
public function testInitializeDatabase() {
|
||||||
$d = new Database();
|
$d = new Database();
|
||||||
$this->assertSame(Database::SCHEMA_VERSION, $d->driverSchemaVersion());
|
$this->assertSame(Database::SCHEMA_VERSION, $d->driverSchemaVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testManuallyInitializeDatabase() {
|
public function testManuallyInitializeDatabase() {
|
||||||
$d = new Database(false);
|
$d = new Database(false);
|
||||||
$this->assertSame(0, $d->driverSchemaVersion());
|
$this->assertSame(0, $d->driverSchemaVersion());
|
||||||
$this->assertTrue($d->driverSchemaUpdate());
|
$this->assertTrue($d->driverSchemaUpdate());
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Test\Database;
|
use JKingWeb\Arsse\Test\Database;
|
||||||
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
||||||
|
@ -101,7 +102,7 @@ trait SeriesSubscription {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
function setUpSeries() {
|
public function setUpSeries() {
|
||||||
$this->data['arsse_feeds']['rows'] = [
|
$this->data['arsse_feeds']['rows'] = [
|
||||||
[1,"http://example.com/feed1", "Ook", "", "",strtotime("now")],
|
[1,"http://example.com/feed1", "Ook", "", "",strtotime("now")],
|
||||||
[2,"http://example.com/feed2", "Eek", "", "",strtotime("now - 1 hour")],
|
[2,"http://example.com/feed2", "Eek", "", "",strtotime("now - 1 hour")],
|
||||||
|
@ -112,7 +113,7 @@ trait SeriesSubscription {
|
||||||
$this->user = "john.doe@example.com";
|
$this->user = "john.doe@example.com";
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddASubscriptionToAnExistingFeed() {
|
public function testAddASubscriptionToAnExistingFeed() {
|
||||||
$url = "http://example.com/feed1";
|
$url = "http://example.com/feed1";
|
||||||
$subID = $this->nextID("arsse_subscriptions");
|
$subID = $this->nextID("arsse_subscriptions");
|
||||||
Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
|
Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
|
||||||
|
@ -127,7 +128,7 @@ trait SeriesSubscription {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddASubscriptionToANewFeed() {
|
public function testAddASubscriptionToANewFeed() {
|
||||||
$url = "http://example.org/feed1";
|
$url = "http://example.org/feed1";
|
||||||
$feedID = $this->nextID("arsse_feeds");
|
$feedID = $this->nextID("arsse_feeds");
|
||||||
$subID = $this->nextID("arsse_subscriptions");
|
$subID = $this->nextID("arsse_subscriptions");
|
||||||
|
@ -144,7 +145,7 @@ trait SeriesSubscription {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddASubscriptionToAnInvalidFeed() {
|
public function testAddASubscriptionToAnInvalidFeed() {
|
||||||
$url = "http://example.org/feed1";
|
$url = "http://example.org/feed1";
|
||||||
$feedID = $this->nextID("arsse_feeds");
|
$feedID = $this->nextID("arsse_feeds");
|
||||||
Phake::when(Arsse::$db)->feedUpdate->thenThrow(new FeedException($url, new \PicoFeed\Client\InvalidUrlException()));
|
Phake::when(Arsse::$db)->feedUpdate->thenThrow(new FeedException($url, new \PicoFeed\Client\InvalidUrlException()));
|
||||||
|
@ -163,20 +164,20 @@ trait SeriesSubscription {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddADuplicateSubscription() {
|
public function testAddADuplicateSubscription() {
|
||||||
$url = "http://example.com/feed2";
|
$url = "http://example.com/feed2";
|
||||||
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionAdd($this->user, $url);
|
Arsse::$db->subscriptionAdd($this->user, $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddASubscriptionWithoutAuthority() {
|
public function testAddASubscriptionWithoutAuthority() {
|
||||||
$url = "http://example.com/feed1";
|
$url = "http://example.com/feed1";
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->subscriptionAdd($this->user, $url);
|
Arsse::$db->subscriptionAdd($this->user, $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveASubscription() {
|
public function testRemoveASubscription() {
|
||||||
$this->assertTrue(Arsse::$db->subscriptionRemove($this->user, 1));
|
$this->assertTrue(Arsse::$db->subscriptionRemove($this->user, 1));
|
||||||
Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionRemove");
|
Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionRemove");
|
||||||
$state = $this->primeExpectations($this->data, [
|
$state = $this->primeExpectations($this->data, [
|
||||||
|
@ -187,24 +188,24 @@ trait SeriesSubscription {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAMissingSubscription() {
|
public function testRemoveAMissingSubscription() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionRemove($this->user, 2112);
|
Arsse::$db->subscriptionRemove($this->user, 2112);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveASubscriptionForTheWrongOwner() {
|
public function testRemoveASubscriptionForTheWrongOwner() {
|
||||||
$this->user = "jane.doe@example.com";
|
$this->user = "jane.doe@example.com";
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionRemove($this->user, 1);
|
Arsse::$db->subscriptionRemove($this->user, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveASubscriptionWithoutAuthority() {
|
public function testRemoveASubscriptionWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->subscriptionRemove($this->user, 1);
|
Arsse::$db->subscriptionRemove($this->user, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListSubscriptions() {
|
public function testListSubscriptions() {
|
||||||
$exp = [
|
$exp = [
|
||||||
[
|
[
|
||||||
'url' => "http://example.com/feed2",
|
'url' => "http://example.com/feed2",
|
||||||
|
@ -232,7 +233,7 @@ trait SeriesSubscription {
|
||||||
$this->assertArraySubset($exp[1], Arsse::$db->subscriptionPropertiesGet($this->user, 3));
|
$this->assertArraySubset($exp[1], Arsse::$db->subscriptionPropertiesGet($this->user, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListSubscriptionsInAFolder() {
|
public function testListSubscriptionsInAFolder() {
|
||||||
$exp = [
|
$exp = [
|
||||||
[
|
[
|
||||||
'url' => "http://example.com/feed3",
|
'url' => "http://example.com/feed3",
|
||||||
|
@ -247,29 +248,29 @@ trait SeriesSubscription {
|
||||||
$this->assertResult($exp, Arsse::$db->subscriptionList($this->user, 2));
|
$this->assertResult($exp, Arsse::$db->subscriptionList($this->user, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListSubscriptionsInAMissingFolder() {
|
public function testListSubscriptionsInAMissingFolder() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionList($this->user, 4);
|
Arsse::$db->subscriptionList($this->user, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListSubscriptionsWithoutAuthority() {
|
public function testListSubscriptionsWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->subscriptionList($this->user);
|
Arsse::$db->subscriptionList($this->user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetThePropertiesOfAMissingSubscription() {
|
public function testGetThePropertiesOfAMissingSubscription() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionPropertiesGet($this->user, 2112);
|
Arsse::$db->subscriptionPropertiesGet($this->user, 2112);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetThePropertiesOfASubscriptionWithoutAuthority() {
|
public function testGetThePropertiesOfASubscriptionWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->subscriptionPropertiesGet($this->user, 1);
|
Arsse::$db->subscriptionPropertiesGet($this->user, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetThePropertiesOfASubscription() {
|
public function testSetThePropertiesOfASubscription() {
|
||||||
Arsse::$db->subscriptionPropertiesSet($this->user, 1, [
|
Arsse::$db->subscriptionPropertiesSet($this->user, 1, [
|
||||||
'title' => "Ook Ook",
|
'title' => "Ook Ook",
|
||||||
'folder' => 3,
|
'folder' => 3,
|
||||||
|
@ -290,40 +291,40 @@ trait SeriesSubscription {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMoveASubscriptionToAMissingFolder() {
|
public function testMoveASubscriptionToAMissingFolder() {
|
||||||
$this->assertException("idMissing", "Db", "ExceptionInput");
|
$this->assertException("idMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => 4]);
|
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => 4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMoveASubscriptionToTheRootFolder() {
|
public function testMoveASubscriptionToTheRootFolder() {
|
||||||
$this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 3, ['folder' => null]));
|
$this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 3, ['folder' => null]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameASubscriptionToABlankTitle() {
|
public function testRenameASubscriptionToABlankTitle() {
|
||||||
$this->assertException("missing", "Db", "ExceptionInput");
|
$this->assertException("missing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => ""]);
|
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => ""]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameASubscriptionToAWhitespaceTitle() {
|
public function testRenameASubscriptionToAWhitespaceTitle() {
|
||||||
$this->assertException("whitespace", "Db", "ExceptionInput");
|
$this->assertException("whitespace", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => " "]);
|
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => " "]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameASubscriptionToFalse() {
|
public function testRenameASubscriptionToFalse() {
|
||||||
$this->assertException("missing", "Db", "ExceptionInput");
|
$this->assertException("missing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => false]);
|
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => false]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameASubscriptionToZero() {
|
public function testRenameASubscriptionToZero() {
|
||||||
$this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => 0]));
|
$this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => 0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetThePropertiesOfAMissingSubscription() {
|
public function testSetThePropertiesOfAMissingSubscription() {
|
||||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||||
Arsse::$db->subscriptionPropertiesSet($this->user, 2112, ['folder' => null]);
|
Arsse::$db->subscriptionPropertiesSet($this->user, 2112, ['folder' => null]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetThePropertiesOfASubscriptionWithoutAuthority() {
|
public function testSetThePropertiesOfASubscriptionWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => null]);
|
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => null]);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\User\Driver as UserDriver;
|
use JKingWeb\Arsse\User\Driver as UserDriver;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
@ -22,7 +23,7 @@ trait SeriesUser {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
function testCheckThatAUserExists() {
|
public function testCheckThatAUserExists() {
|
||||||
$this->assertTrue(Arsse::$db->userExists("jane.doe@example.com"));
|
$this->assertTrue(Arsse::$db->userExists("jane.doe@example.com"));
|
||||||
$this->assertFalse(Arsse::$db->userExists("jane.doe@example.org"));
|
$this->assertFalse(Arsse::$db->userExists("jane.doe@example.org"));
|
||||||
Phake::verify(Arsse::$user)->authorize("jane.doe@example.com", "userExists");
|
Phake::verify(Arsse::$user)->authorize("jane.doe@example.com", "userExists");
|
||||||
|
@ -30,31 +31,31 @@ trait SeriesUser {
|
||||||
$this->compareExpectations($this->data);
|
$this->compareExpectations($this->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCheckThatAUserExistsWithoutAuthority() {
|
public function testCheckThatAUserExistsWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userExists("jane.doe@example.com");
|
Arsse::$db->userExists("jane.doe@example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetAPassword() {
|
public function testGetAPassword() {
|
||||||
$hash = Arsse::$db->userPasswordGet("admin@example.net");
|
$hash = Arsse::$db->userPasswordGet("admin@example.net");
|
||||||
$this->assertSame('$2y$10$PbcG2ZR3Z8TuPzM7aHTF8.v61dtCjzjK78gdZJcp4UePE8T9jEgBW', $hash);
|
$this->assertSame('$2y$10$PbcG2ZR3Z8TuPzM7aHTF8.v61dtCjzjK78gdZJcp4UePE8T9jEgBW', $hash);
|
||||||
Phake::verify(Arsse::$user)->authorize("admin@example.net", "userPasswordGet");
|
Phake::verify(Arsse::$user)->authorize("admin@example.net", "userPasswordGet");
|
||||||
$this->assertTrue(password_verify("secret", $hash));
|
$this->assertTrue(password_verify("secret", $hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetThePasswordOfAMissingUser() {
|
public function testGetThePasswordOfAMissingUser() {
|
||||||
$this->assertException("doesNotExist", "User");
|
$this->assertException("doesNotExist", "User");
|
||||||
Arsse::$db->userPasswordGet("john.doe@example.org");
|
Arsse::$db->userPasswordGet("john.doe@example.org");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetAPasswordWithoutAuthority() {
|
public function testGetAPasswordWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userPasswordGet("admin@example.net");
|
Arsse::$db->userPasswordGet("admin@example.net");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddANewUser() {
|
public function testAddANewUser() {
|
||||||
$this->assertSame("", Arsse::$db->userAdd("john.doe@example.org", ""));
|
$this->assertSame("", Arsse::$db->userAdd("john.doe@example.org", ""));
|
||||||
Phake::verify(Arsse::$user)->authorize("john.doe@example.org", "userAdd");
|
Phake::verify(Arsse::$user)->authorize("john.doe@example.org", "userAdd");
|
||||||
$state = $this->primeExpectations($this->data, ['arsse_users' => ['id','name','rights']]);
|
$state = $this->primeExpectations($this->data, ['arsse_users' => ['id','name','rights']]);
|
||||||
|
@ -66,7 +67,7 @@ trait SeriesUser {
|
||||||
* @depends testGetAPassword
|
* @depends testGetAPassword
|
||||||
* @depends testAddANewUser
|
* @depends testAddANewUser
|
||||||
*/
|
*/
|
||||||
function testAddANewUserWithARandomPassword() {
|
public function testAddANewUserWithARandomPassword() {
|
||||||
$user1 = "john.doe@example.org";
|
$user1 = "john.doe@example.org";
|
||||||
$user2 = "john.doe@example.net";
|
$user2 = "john.doe@example.net";
|
||||||
$pass1 = Arsse::$db->userAdd($user1);
|
$pass1 = Arsse::$db->userAdd($user1);
|
||||||
|
@ -84,18 +85,18 @@ trait SeriesUser {
|
||||||
$this->assertTrue(password_verify($pass2, $hash2), "Failed verifying password of $user2 '$pass2' against hash '$hash2'.");
|
$this->assertTrue(password_verify($pass2, $hash2), "Failed verifying password of $user2 '$pass2' against hash '$hash2'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddAnExistingUser() {
|
public function testAddAnExistingUser() {
|
||||||
$this->assertException("alreadyExists", "User");
|
$this->assertException("alreadyExists", "User");
|
||||||
Arsse::$db->userAdd("john.doe@example.com", "");
|
Arsse::$db->userAdd("john.doe@example.com", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddANewUserWithoutAuthority() {
|
public function testAddANewUserWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userAdd("john.doe@example.org", "");
|
Arsse::$db->userAdd("john.doe@example.org", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAUser() {
|
public function testRemoveAUser() {
|
||||||
$this->assertTrue(Arsse::$db->userRemove("admin@example.net"));
|
$this->assertTrue(Arsse::$db->userRemove("admin@example.net"));
|
||||||
Phake::verify(Arsse::$user)->authorize("admin@example.net", "userRemove");
|
Phake::verify(Arsse::$user)->authorize("admin@example.net", "userRemove");
|
||||||
$state = $this->primeExpectations($this->data, ['arsse_users' => ['id']]);
|
$state = $this->primeExpectations($this->data, ['arsse_users' => ['id']]);
|
||||||
|
@ -103,36 +104,36 @@ trait SeriesUser {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAMissingUser() {
|
public function testRemoveAMissingUser() {
|
||||||
$this->assertException("doesNotExist", "User");
|
$this->assertException("doesNotExist", "User");
|
||||||
Arsse::$db->userRemove("john.doe@example.org");
|
Arsse::$db->userRemove("john.doe@example.org");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAUserWithoutAuthority() {
|
public function testRemoveAUserWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userRemove("admin@example.net");
|
Arsse::$db->userRemove("admin@example.net");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListAllUsers() {
|
public function testListAllUsers() {
|
||||||
$users = ["admin@example.net", "jane.doe@example.com", "john.doe@example.com"];
|
$users = ["admin@example.net", "jane.doe@example.com", "john.doe@example.com"];
|
||||||
$this->assertSame($users, Arsse::$db->userList());
|
$this->assertSame($users, Arsse::$db->userList());
|
||||||
Phake::verify(Arsse::$user)->authorize("", "userList");
|
Phake::verify(Arsse::$user)->authorize("", "userList");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListUsersOnADomain() {
|
public function testListUsersOnADomain() {
|
||||||
$users = ["jane.doe@example.com", "john.doe@example.com"];
|
$users = ["jane.doe@example.com", "john.doe@example.com"];
|
||||||
$this->assertSame($users, Arsse::$db->userList("example.com"));
|
$this->assertSame($users, Arsse::$db->userList("example.com"));
|
||||||
Phake::verify(Arsse::$user)->authorize("@example.com", "userList");
|
Phake::verify(Arsse::$user)->authorize("@example.com", "userList");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListAllUsersWithoutAuthority() {
|
public function testListAllUsersWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userList();
|
Arsse::$db->userList();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListUsersOnADomainWithoutAuthority() {
|
public function testListUsersOnADomainWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userList("example.com");
|
Arsse::$db->userList("example.com");
|
||||||
|
@ -141,7 +142,7 @@ trait SeriesUser {
|
||||||
/**
|
/**
|
||||||
* @depends testGetAPassword
|
* @depends testGetAPassword
|
||||||
*/
|
*/
|
||||||
function testSetAPassword() {
|
public function testSetAPassword() {
|
||||||
$user = "john.doe@example.com";
|
$user = "john.doe@example.com";
|
||||||
$this->assertEquals("", Arsse::$db->userPasswordGet($user));
|
$this->assertEquals("", Arsse::$db->userPasswordGet($user));
|
||||||
$pass = Arsse::$db->userPasswordSet($user, "secret");
|
$pass = Arsse::$db->userPasswordSet($user, "secret");
|
||||||
|
@ -150,25 +151,25 @@ trait SeriesUser {
|
||||||
Phake::verify(Arsse::$user)->authorize($user, "userPasswordSet");
|
Phake::verify(Arsse::$user)->authorize($user, "userPasswordSet");
|
||||||
$this->assertTrue(password_verify($pass, $hash), "Failed verifying password of $user '$pass' against hash '$hash'.");
|
$this->assertTrue(password_verify($pass, $hash), "Failed verifying password of $user '$pass' against hash '$hash'.");
|
||||||
}
|
}
|
||||||
function testSetARandomPassword() {
|
public function testSetARandomPassword() {
|
||||||
$user = "john.doe@example.com";
|
$user = "john.doe@example.com";
|
||||||
$this->assertEquals("", Arsse::$db->userPasswordGet($user));
|
$this->assertEquals("", Arsse::$db->userPasswordGet($user));
|
||||||
$pass = Arsse::$db->userPasswordSet($user);
|
$pass = Arsse::$db->userPasswordSet($user);
|
||||||
$hash = Arsse::$db->userPasswordGet($user);
|
$hash = Arsse::$db->userPasswordGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetThePasswordOfAMissingUser() {
|
public function testSetThePasswordOfAMissingUser() {
|
||||||
$this->assertException("doesNotExist", "User");
|
$this->assertException("doesNotExist", "User");
|
||||||
Arsse::$db->userPasswordSet("john.doe@example.org", "secret");
|
Arsse::$db->userPasswordSet("john.doe@example.org", "secret");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetAPasswordWithoutAuthority() {
|
public function testSetAPasswordWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userPasswordSet("john.doe@example.com", "secret");
|
Arsse::$db->userPasswordSet("john.doe@example.com", "secret");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetUserProperties() {
|
public function testGetUserProperties() {
|
||||||
$exp = [
|
$exp = [
|
||||||
'name' => 'Hard Lip Herbert',
|
'name' => 'Hard Lip Herbert',
|
||||||
'rights' => UserDriver::RIGHTS_GLOBAL_ADMIN,
|
'rights' => UserDriver::RIGHTS_GLOBAL_ADMIN,
|
||||||
|
@ -179,18 +180,18 @@ trait SeriesUser {
|
||||||
$this->assertArrayNotHasKey("password", $props);
|
$this->assertArrayNotHasKey("password", $props);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetThePropertiesOfAMissingUser() {
|
public function testGetThePropertiesOfAMissingUser() {
|
||||||
$this->assertException("doesNotExist", "User");
|
$this->assertException("doesNotExist", "User");
|
||||||
Arsse::$db->userPropertiesGet("john.doe@example.org");
|
Arsse::$db->userPropertiesGet("john.doe@example.org");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetUserPropertiesWithoutAuthority() {
|
public function testGetUserPropertiesWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userPropertiesGet("john.doe@example.com");
|
Arsse::$db->userPropertiesGet("john.doe@example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetUserProperties() {
|
public function testSetUserProperties() {
|
||||||
$try = [
|
$try = [
|
||||||
'name' => 'James Kirk', // only this should actually change
|
'name' => 'James Kirk', // only this should actually change
|
||||||
'password' => '000destruct0',
|
'password' => '000destruct0',
|
||||||
|
@ -210,20 +211,20 @@ trait SeriesUser {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetThePropertiesOfAMissingUser() {
|
public function testSetThePropertiesOfAMissingUser() {
|
||||||
$try = ['name' => 'John Doe'];
|
$try = ['name' => 'John Doe'];
|
||||||
$this->assertException("doesNotExist", "User");
|
$this->assertException("doesNotExist", "User");
|
||||||
Arsse::$db->userPropertiesSet("john.doe@example.org", $try);
|
Arsse::$db->userPropertiesSet("john.doe@example.org", $try);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetUserPropertiesWithoutAuthority() {
|
public function testSetUserPropertiesWithoutAuthority() {
|
||||||
$try = ['name' => 'John Doe'];
|
$try = ['name' => 'John Doe'];
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userPropertiesSet("john.doe@example.com", $try);
|
Arsse::$db->userPropertiesSet("john.doe@example.com", $try);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetUserRights() {
|
public function testGetUserRights() {
|
||||||
$user1 = "john.doe@example.com";
|
$user1 = "john.doe@example.com";
|
||||||
$user2 = "admin@example.net";
|
$user2 = "admin@example.net";
|
||||||
$this->assertSame(UserDriver::RIGHTS_NONE, Arsse::$db->userRightsGet($user1));
|
$this->assertSame(UserDriver::RIGHTS_NONE, Arsse::$db->userRightsGet($user1));
|
||||||
|
@ -232,18 +233,18 @@ trait SeriesUser {
|
||||||
Phake::verify(Arsse::$user)->authorize($user2, "userRightsGet");
|
Phake::verify(Arsse::$user)->authorize($user2, "userRightsGet");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetTheRightsOfAMissingUser() {
|
public function testGetTheRightsOfAMissingUser() {
|
||||||
$this->assertSame(UserDriver::RIGHTS_NONE, Arsse::$db->userRightsGet("john.doe@example.org"));
|
$this->assertSame(UserDriver::RIGHTS_NONE, Arsse::$db->userRightsGet("john.doe@example.org"));
|
||||||
Phake::verify(Arsse::$user)->authorize("john.doe@example.org", "userRightsGet");
|
Phake::verify(Arsse::$user)->authorize("john.doe@example.org", "userRightsGet");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetUserRightsWithoutAuthority() {
|
public function testGetUserRightsWithoutAuthority() {
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
Arsse::$db->userRightsGet("john.doe@example.com");
|
Arsse::$db->userRightsGet("john.doe@example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetUserRights() {
|
public function testSetUserRights() {
|
||||||
$user = "john.doe@example.com";
|
$user = "john.doe@example.com";
|
||||||
$rights = UserDriver::RIGHTS_GLOBAL_ADMIN;
|
$rights = UserDriver::RIGHTS_GLOBAL_ADMIN;
|
||||||
$this->assertTrue(Arsse::$db->userRightsSet($user, $rights));
|
$this->assertTrue(Arsse::$db->userRightsSet($user, $rights));
|
||||||
|
@ -253,13 +254,13 @@ trait SeriesUser {
|
||||||
$this->compareExpectations($state);
|
$this->compareExpectations($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetTheRightsOfAMissingUser() {
|
public function testSetTheRightsOfAMissingUser() {
|
||||||
$rights = UserDriver::RIGHTS_GLOBAL_ADMIN;
|
$rights = UserDriver::RIGHTS_GLOBAL_ADMIN;
|
||||||
$this->assertException("doesNotExist", "User");
|
$this->assertException("doesNotExist", "User");
|
||||||
Arsse::$db->userRightsSet("john.doe@example.org", $rights);
|
Arsse::$db->userRightsSet("john.doe@example.org", $rights);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetUserRightsWithoutAuthority() {
|
public function testSetUserRightsWithoutAuthority() {
|
||||||
$rights = UserDriver::RIGHTS_GLOBAL_ADMIN;
|
$rights = UserDriver::RIGHTS_GLOBAL_ADMIN;
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Database;
|
namespace JKingWeb\Arsse\Test\Database;
|
||||||
|
|
||||||
use JKingWeb\Arsse\User\Driver as UserDriver;
|
use JKingWeb\Arsse\User\Driver as UserDriver;
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Conf;
|
use JKingWeb\Arsse\Conf;
|
||||||
|
@ -13,7 +14,7 @@ trait Setup {
|
||||||
protected $drv;
|
protected $drv;
|
||||||
protected $primed = false;
|
protected $primed = false;
|
||||||
|
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
// establish a clean baseline
|
// establish a clean baseline
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
// create a default configuration
|
// create a default configuration
|
||||||
|
@ -27,21 +28,27 @@ trait Setup {
|
||||||
Arsse::$user = Phake::mock(User::class);
|
Arsse::$user = Phake::mock(User::class);
|
||||||
Phake::when(Arsse::$user)->authorize->thenReturn(true);
|
Phake::when(Arsse::$user)->authorize->thenReturn(true);
|
||||||
// call the additional setup method if it exists
|
// call the additional setup method if it exists
|
||||||
if(method_exists($this, "setUpSeries")) $this->setUpSeries();
|
if (method_exists($this, "setUpSeries")) {
|
||||||
|
$this->setUpSeries();
|
||||||
|
}
|
||||||
// prime the database with series data if it hasn't already been done
|
// prime the database with series data if it hasn't already been done
|
||||||
if(!$this->primed && isset($this->data)) $this->primeDatabase($this->data);
|
if (!$this->primed && isset($this->data)) {
|
||||||
|
$this->primeDatabase($this->data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
// call the additional teardiwn method if it exists
|
// call the additional teardiwn method if it exists
|
||||||
if(method_exists($this, "tearDownSeries")) $this->tearDownSeries();
|
if (method_exists($this, "tearDownSeries")) {
|
||||||
|
$this->tearDownSeries();
|
||||||
|
}
|
||||||
// clean up
|
// clean up
|
||||||
$this->primed = false;
|
$this->primed = false;
|
||||||
$this->drv = null;
|
$this->drv = null;
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function primeDatabase(array $data): bool {
|
public function primeDatabase(array $data): bool {
|
||||||
$tr = $this->drv->begin();
|
$tr = $this->drv->begin();
|
||||||
foreach ($data as $table => $info) {
|
foreach ($data as $table => $info) {
|
||||||
$cols = implode(",", array_keys($info['columns']));
|
$cols = implode(",", array_keys($info['columns']));
|
||||||
|
@ -57,7 +64,7 @@ trait Setup {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareExpectations(array $expected): bool {
|
public function compareExpectations(array $expected): bool {
|
||||||
foreach ($expected as $table => $info) {
|
foreach ($expected as $table => $info) {
|
||||||
$cols = implode(",", array_keys($info['columns']));
|
$cols = implode(",", array_keys($info['columns']));
|
||||||
$data = $this->drv->prepare("SELECT $cols from $table")->run()->getAll();
|
$data = $this->drv->prepare("SELECT $cols from $table")->run()->getAll();
|
||||||
|
@ -74,7 +81,7 @@ trait Setup {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function primeExpectations(array $source, array $tableSpecs = null): array {
|
public function primeExpectations(array $source, array $tableSpecs = null): array {
|
||||||
$out = [];
|
$out = [];
|
||||||
foreach ($tableSpecs as $table => $columns) {
|
foreach ($tableSpecs as $table => $columns) {
|
||||||
// make sure the source has the table we want
|
// make sure the source has the table we want
|
||||||
|
@ -101,7 +108,7 @@ trait Setup {
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertResult(array $expected, Result $data) {
|
public function assertResult(array $expected, Result $data) {
|
||||||
$data = $data->getAll();
|
$data = $data->getAll();
|
||||||
$this->assertCount(sizeof($expected), $data, "Number of result rows (".sizeof($data).") differs from number of expected rows (".sizeof($expected).")");
|
$this->assertCount(sizeof($expected), $data, "Number of result rows (".sizeof($data).") differs from number of expected rows (".sizeof($expected).")");
|
||||||
if (sizeof($expected)) {
|
if (sizeof($expected)) {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Db;
|
namespace JKingWeb\Arsse\Test\Db;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Db\Statement;
|
use JKingWeb\Arsse\Db\Statement;
|
||||||
|
|
||||||
trait BindingTests {
|
trait BindingTests {
|
||||||
function testBindNull() {
|
public function testBindNull() {
|
||||||
$input = null;
|
$input = null;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
|
@ -34,7 +35,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindTrue() {
|
public function testBindTrue() {
|
||||||
$input = true;
|
$input = true;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
|
@ -51,7 +52,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindFalse() {
|
public function testBindFalse() {
|
||||||
$input = false;
|
$input = false;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
|
@ -68,7 +69,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindInteger() {
|
public function testBindInteger() {
|
||||||
$input = 2112;
|
$input = 2112;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
|
@ -85,7 +86,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindIntegerZero() {
|
public function testBindIntegerZero() {
|
||||||
$input = 0;
|
$input = 0;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
|
@ -102,7 +103,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindFloat() {
|
public function testBindFloat() {
|
||||||
$input = 2112.0;
|
$input = 2112.0;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
|
@ -119,7 +120,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindFloatZero() {
|
public function testBindFloatZero() {
|
||||||
$input = 0.0;
|
$input = 0.0;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
|
@ -136,7 +137,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindAsciiString() {
|
public function testBindAsciiString() {
|
||||||
$input = "Random string";
|
$input = "Random string";
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
|
@ -153,7 +154,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindUtf8String() {
|
public function testBindUtf8String() {
|
||||||
$input = "é";
|
$input = "é";
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
|
@ -170,7 +171,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindBinaryString() {
|
public function testBindBinaryString() {
|
||||||
// FIXME: This test may be unreliable; SQLite happily stores invalid UTF-8 text as bytes untouched, but other engines probably don't do this
|
// FIXME: This test may be unreliable; SQLite happily stores invalid UTF-8 text as bytes untouched, but other engines probably don't do this
|
||||||
$input = chr(233);
|
$input = chr(233);
|
||||||
$exp = [
|
$exp = [
|
||||||
|
@ -188,7 +189,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindIso8601DateString() {
|
public function testBindIso8601DateString() {
|
||||||
$input = "2017-01-09T13:11:17";
|
$input = "2017-01-09T13:11:17";
|
||||||
$time = strtotime($input);
|
$time = strtotime($input);
|
||||||
$exp = [
|
$exp = [
|
||||||
|
@ -206,7 +207,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindArbitraryDateString() {
|
public function testBindArbitraryDateString() {
|
||||||
$input = "Today";
|
$input = "Today";
|
||||||
$time = strtotime($input);
|
$time = strtotime($input);
|
||||||
$exp = [
|
$exp = [
|
||||||
|
@ -224,7 +225,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindMutableDateObject($class = '\DateTime') {
|
public function testBindMutableDateObject($class = '\DateTime') {
|
||||||
$input = new $class("Noon Today");
|
$input = new $class("Noon Today");
|
||||||
$time = $input->getTimestamp();
|
$time = $input->getTimestamp();
|
||||||
$exp = [
|
$exp = [
|
||||||
|
@ -242,7 +243,7 @@ trait BindingTests {
|
||||||
$this->checkBinding($input, $exp, true);
|
$this->checkBinding($input, $exp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindImmutableDateObject() {
|
public function testBindImmutableDateObject() {
|
||||||
$this->testBindMutableDateObject('\DateTimeImmutable');
|
$this->testBindMutableDateObject('\DateTimeImmutable');
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Lang;
|
namespace JKingWeb\Arsse\Test\Lang;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Lang;
|
use JKingWeb\Arsse\Lang;
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use org\bovigo\vfs\vfsStream;
|
use org\bovigo\vfs\vfsStream;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
trait Setup {
|
trait Setup {
|
||||||
function setUp() {
|
public function setUp() {
|
||||||
// test files
|
// test files
|
||||||
$this->files = [
|
$this->files = [
|
||||||
'en.php' => '<?php return ["Test.presentText" => "and the Philosopher\'s Stone"];',
|
'en.php' => '<?php return ["Test.presentText" => "and the Philosopher\'s Stone"];',
|
||||||
|
@ -40,16 +39,20 @@ trait Setup {
|
||||||
Arsse::$lang = Phake::mock(Lang::class);
|
Arsse::$lang = Phake::mock(Lang::class);
|
||||||
Phake::when(Arsse::$lang)->msg->thenReturn("");
|
Phake::when(Arsse::$lang)->msg->thenReturn("");
|
||||||
// call the additional setup method if it exists
|
// call the additional setup method if it exists
|
||||||
if(method_exists($this, "setUpSeries")) $this->setUpSeries();
|
if (method_exists($this, "setUpSeries")) {
|
||||||
|
$this->setUpSeries();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
// verify calls to the mock Lang object
|
// verify calls to the mock Lang object
|
||||||
Phake::verify(Arsse::$lang, Phake::atLeast(0))->msg($this->isType("string"), $this->anything());
|
Phake::verify(Arsse::$lang, Phake::atLeast(0))->msg($this->isType("string"), $this->anything());
|
||||||
Phake::verifyNoOtherInteractions(Arsse::$lang);
|
Phake::verifyNoOtherInteractions(Arsse::$lang);
|
||||||
// clean up
|
// clean up
|
||||||
$this->clearData(true);
|
$this->clearData(true);
|
||||||
// call the additional teardiwn method if it exists
|
// call the additional teardiwn method if it exists
|
||||||
if(method_exists($this, "tearDownSeries")) $this->tearDownSeries();
|
if (method_exists($this, "tearDownSeries")) {
|
||||||
|
$this->tearDownSeries();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\Lang;
|
namespace JKingWeb\Arsse\Test\Lang;
|
||||||
|
|
||||||
use Webmozart\Glob\Glob;
|
use Webmozart\Glob\Glob;
|
||||||
|
|
||||||
class TestLang extends \JKingWeb\Arsse\Lang {
|
class TestLang extends \JKingWeb\Arsse\Lang {
|
||||||
|
|
||||||
protected function globFiles(string $path): array {
|
protected function globFiles(string $path): array {
|
||||||
return Glob::glob($this->path."*.php");
|
return Glob::glob($this->path."*.php");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\User;
|
namespace JKingWeb\Arsse\Test\User;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Conf;
|
use JKingWeb\Arsse\Conf;
|
||||||
use JKingWeb\Arsse\User;
|
use JKingWeb\Arsse\User;
|
||||||
|
@ -8,8 +9,7 @@ use JKingWeb\Arsse\User\Driver;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
|
||||||
trait CommonTests {
|
trait CommonTests {
|
||||||
|
public function setUp() {
|
||||||
function setUp() {
|
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->userDriver = $this->drv;
|
$conf->userDriver = $this->drv;
|
||||||
|
@ -21,58 +21,62 @@ trait CommonTests {
|
||||||
$_SERVER['PHP_AUTH_USER'] = self::USER1;
|
$_SERVER['PHP_AUTH_USER'] = self::USER1;
|
||||||
$_SERVER['PHP_AUTH_PW'] = "secret";
|
$_SERVER['PHP_AUTH_PW'] = "secret";
|
||||||
// call the additional setup method if it exists
|
// call the additional setup method if it exists
|
||||||
if(method_exists($this, "setUpSeries")) $this->setUpSeries();
|
if (method_exists($this, "setUpSeries")) {
|
||||||
|
$this->setUpSeries();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
public function tearDown() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
// call the additional teardiwn method if it exists
|
// call the additional teardiwn method if it exists
|
||||||
if(method_exists($this, "tearDownSeries")) $this->tearDownSeries();
|
if (method_exists($this, "tearDownSeries")) {
|
||||||
|
$this->tearDownSeries();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListUsers() {
|
public function testListUsers() {
|
||||||
$this->assertCount(0, Arsse::$user->list());
|
$this->assertCount(0, Arsse::$user->list());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCheckIfAUserDoesNotExist() {
|
public function testCheckIfAUserDoesNotExist() {
|
||||||
$this->assertFalse(Arsse::$user->exists(self::USER1));
|
$this->assertFalse(Arsse::$user->exists(self::USER1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddAUser() {
|
public function testAddAUser() {
|
||||||
Arsse::$user->add(self::USER1, "");
|
Arsse::$user->add(self::USER1, "");
|
||||||
$this->assertCount(1, Arsse::$user->list());
|
$this->assertCount(1, Arsse::$user->list());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCheckIfAUserDoesExist() {
|
public function testCheckIfAUserDoesExist() {
|
||||||
Arsse::$user->add(self::USER1, "");
|
Arsse::$user->add(self::USER1, "");
|
||||||
$this->assertTrue(Arsse::$user->exists(self::USER1));
|
$this->assertTrue(Arsse::$user->exists(self::USER1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddADuplicateUser() {
|
public function testAddADuplicateUser() {
|
||||||
Arsse::$user->add(self::USER1, "");
|
Arsse::$user->add(self::USER1, "");
|
||||||
$this->assertException("alreadyExists", "User");
|
$this->assertException("alreadyExists", "User");
|
||||||
Arsse::$user->add(self::USER1, "");
|
Arsse::$user->add(self::USER1, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddMultipleUsers() {
|
public function testAddMultipleUsers() {
|
||||||
Arsse::$user->add(self::USER1, "");
|
Arsse::$user->add(self::USER1, "");
|
||||||
Arsse::$user->add(self::USER2, "");
|
Arsse::$user->add(self::USER2, "");
|
||||||
$this->assertCount(2, Arsse::$user->list());
|
$this->assertCount(2, Arsse::$user->list());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAUser() {
|
public function testRemoveAUser() {
|
||||||
Arsse::$user->add(self::USER1, "");
|
Arsse::$user->add(self::USER1, "");
|
||||||
$this->assertCount(1, Arsse::$user->list());
|
$this->assertCount(1, Arsse::$user->list());
|
||||||
Arsse::$user->remove(self::USER1);
|
Arsse::$user->remove(self::USER1);
|
||||||
$this->assertCount(0, Arsse::$user->list());
|
$this->assertCount(0, Arsse::$user->list());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAMissingUser() {
|
public function testRemoveAMissingUser() {
|
||||||
$this->assertException("doesNotExist", "User");
|
$this->assertException("doesNotExist", "User");
|
||||||
Arsse::$user->remove(self::USER1);
|
Arsse::$user->remove(self::USER1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAuthenticateAUser() {
|
public function testAuthenticateAUser() {
|
||||||
$_SERVER['PHP_AUTH_USER'] = self::USER1;
|
$_SERVER['PHP_AUTH_USER'] = self::USER1;
|
||||||
$_SERVER['PHP_AUTH_PW'] = "secret";
|
$_SERVER['PHP_AUTH_PW'] = "secret";
|
||||||
Arsse::$user->add(self::USER1, "secret");
|
Arsse::$user->add(self::USER1, "secret");
|
||||||
|
@ -83,7 +87,7 @@ trait CommonTests {
|
||||||
$this->assertTrue(Arsse::$user->auth(self::USER2, ""));
|
$this->assertTrue(Arsse::$user->auth(self::USER2, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testChangeAPassword() {
|
public function testChangeAPassword() {
|
||||||
Arsse::$user->add(self::USER1, "secret");
|
Arsse::$user->add(self::USER1, "secret");
|
||||||
$this->assertEquals("superman", Arsse::$user->passwordSet(self::USER1, "superman"));
|
$this->assertEquals("superman", Arsse::$user->passwordSet(self::USER1, "superman"));
|
||||||
$this->assertTrue(Arsse::$user->auth(self::USER1, "superman"));
|
$this->assertTrue(Arsse::$user->auth(self::USER1, "superman"));
|
||||||
|
@ -93,12 +97,12 @@ trait CommonTests {
|
||||||
$this->assertEquals(Arsse::$conf->userTempPasswordLength, strlen(Arsse::$user->passwordSet(self::USER1)));
|
$this->assertEquals(Arsse::$conf->userTempPasswordLength, strlen(Arsse::$user->passwordSet(self::USER1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testChangeAPasswordForAMissingUser() {
|
public function testChangeAPasswordForAMissingUser() {
|
||||||
$this->assertException("doesNotExist", "User");
|
$this->assertException("doesNotExist", "User");
|
||||||
Arsse::$user->passwordSet(self::USER1, "superman");
|
Arsse::$user->passwordSet(self::USER1, "superman");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetThePropertiesOfAUser() {
|
public function testGetThePropertiesOfAUser() {
|
||||||
Arsse::$user->add(self::USER1, "secret");
|
Arsse::$user->add(self::USER1, "secret");
|
||||||
$p = Arsse::$user->propertiesGet(self::USER1);
|
$p = Arsse::$user->propertiesGet(self::USER1);
|
||||||
$this->assertArrayHasKey('id', $p);
|
$this->assertArrayHasKey('id', $p);
|
||||||
|
@ -109,7 +113,7 @@ trait CommonTests {
|
||||||
$this->assertEquals(self::USER1, $p['name']);
|
$this->assertEquals(self::USER1, $p['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetThePropertiesOfAUser() {
|
public function testSetThePropertiesOfAUser() {
|
||||||
$pSet = [
|
$pSet = [
|
||||||
'name' => 'John Doe',
|
'name' => 'John Doe',
|
||||||
'id' => 'invalid',
|
'id' => 'invalid',
|
||||||
|
@ -131,12 +135,12 @@ trait CommonTests {
|
||||||
$this->assertFalse(Arsse::$user->auth(self::USER1, "superman"));
|
$this->assertFalse(Arsse::$user->auth(self::USER1, "superman"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGetTheRightsOfAUser() {
|
public function testGetTheRightsOfAUser() {
|
||||||
Arsse::$user->add(self::USER1, "");
|
Arsse::$user->add(self::USER1, "");
|
||||||
$this->assertEquals(Driver::RIGHTS_NONE, Arsse::$user->rightsGet(self::USER1));
|
$this->assertEquals(Driver::RIGHTS_NONE, Arsse::$user->rightsGet(self::USER1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSetTheRightsOfAUser() {
|
public function testSetTheRightsOfAUser() {
|
||||||
Arsse::$user->add(self::USER1, "");
|
Arsse::$user->add(self::USER1, "");
|
||||||
Arsse::$user->rightsSet(self::USER1, Driver::RIGHTS_GLOBAL_ADMIN);
|
Arsse::$user->rightsSet(self::USER1, Driver::RIGHTS_GLOBAL_ADMIN);
|
||||||
$this->assertEquals(Driver::RIGHTS_GLOBAL_ADMIN, Arsse::$user->rightsGet(self::USER1));
|
$this->assertEquals(Driver::RIGHTS_GLOBAL_ADMIN, Arsse::$user->rightsGet(self::USER1));
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\User;
|
namespace JKingWeb\Arsse\Test\User;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\User\Driver;
|
use JKingWeb\Arsse\User\Driver;
|
||||||
use JKingWeb\Arsse\User\Exception;
|
use JKingWeb\Arsse\User\Exception;
|
||||||
|
@ -8,80 +9,121 @@ use JKingWeb\Arsse\User\ExceptionAuthz;
|
||||||
use PasswordGenerator\Generator as PassGen;
|
use PasswordGenerator\Generator as PassGen;
|
||||||
|
|
||||||
class Database extends DriverSkeleton {
|
class Database extends DriverSkeleton {
|
||||||
|
|
||||||
public $db = [];
|
public $db = [];
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function userExists(string $user): bool {
|
public function userExists(string $user): bool {
|
||||||
if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
return parent::userExists($user);
|
return parent::userExists($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userAdd(string $user, string $password = null): string {
|
public function userAdd(string $user, string $password = null): string {
|
||||||
if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
if($this->userExists($user)) throw new Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]);
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
if($password===null) $password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
}
|
||||||
|
if ($this->userExists($user)) {
|
||||||
|
throw new Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if ($password===null) {
|
||||||
|
$password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
||||||
|
}
|
||||||
return parent::userAdd($user, $password);
|
return parent::userAdd($user, $password);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRemove(string $user): bool {
|
public function userRemove(string $user): bool {
|
||||||
if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
return parent::userRemove($user);
|
return parent::userRemove($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userList(string $domain = null): array {
|
public function userList(string $domain = null): array {
|
||||||
if ($domain===null) {
|
if ($domain===null) {
|
||||||
if(!Arsse::$user->authorize("", __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => "global"]);
|
if (!Arsse::$user->authorize("", __FUNCTION__)) {
|
||||||
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => "global"]);
|
||||||
|
}
|
||||||
return parent::userList();
|
return parent::userList();
|
||||||
} else {
|
} else {
|
||||||
$suffix = '@'.$domain;
|
$suffix = '@'.$domain;
|
||||||
if(!Arsse::$user->authorize($suffix, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $domain]);
|
if (!Arsse::$user->authorize($suffix, __FUNCTION__)) {
|
||||||
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $domain]);
|
||||||
|
}
|
||||||
return parent::userList($domain);
|
return parent::userList($domain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
||||||
if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
if($newPassword===null) $newPassword = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
}
|
||||||
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if ($newPassword===null) {
|
||||||
|
$newPassword = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
||||||
|
}
|
||||||
return parent::userPasswordSet($user, $newPassword);
|
return parent::userPasswordSet($user, $newPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPropertiesGet(string $user): array {
|
public function userPropertiesGet(string $user): array {
|
||||||
if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
$out = parent::userPropertiesGet($user);
|
$out = parent::userPropertiesGet($user);
|
||||||
unset($out['password']);
|
unset($out['password']);
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPropertiesSet(string $user, array $properties): array {
|
public function userPropertiesSet(string $user, array $properties): array {
|
||||||
if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
parent::userPropertiesSet($user, $properties);
|
parent::userPropertiesSet($user, $properties);
|
||||||
return $this->userPropertiesGet($user);
|
return $this->userPropertiesGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsGet(string $user): int {
|
public function userRightsGet(string $user): int {
|
||||||
if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
return parent::userRightsGet($user);
|
return parent::userRightsGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsSet(string $user, int $level): bool {
|
public function userRightsSet(string $user, int $level): bool {
|
||||||
if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
return parent::userRightsSet($user, $level);
|
return parent::userRightsSet($user, $level);
|
||||||
}
|
}
|
||||||
|
|
||||||
// specific to mock database
|
// specific to mock database
|
||||||
|
|
||||||
function userPasswordGet(string $user): string {
|
public function userPasswordGet(string $user): string {
|
||||||
if(!Arsse::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
return $this->db[$user]['password'];
|
return $this->db[$user]['password'];
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\User;
|
namespace JKingWeb\Arsse\Test\User;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\User\Driver;
|
use JKingWeb\Arsse\User\Driver;
|
||||||
use JKingWeb\Arsse\User\Exception;
|
use JKingWeb\Arsse\User\Exception;
|
||||||
use PasswordGenerator\Generator as PassGen;
|
use PasswordGenerator\Generator as PassGen;
|
||||||
|
|
||||||
class DriverExternalMock extends DriverSkeleton implements Driver {
|
class DriverExternalMock extends DriverSkeleton implements Driver {
|
||||||
|
|
||||||
public $db = [];
|
public $db = [];
|
||||||
protected $functions = [
|
protected $functions = [
|
||||||
"auth" => Driver::FUNC_EXTERNAL,
|
"auth" => Driver::FUNC_EXTERNAL,
|
||||||
|
@ -22,12 +22,14 @@ class DriverExternalMock extends DriverSkeleton implements Driver {
|
||||||
"userRightsSet" => Driver::FUNC_EXTERNAL,
|
"userRightsSet" => Driver::FUNC_EXTERNAL,
|
||||||
];
|
];
|
||||||
|
|
||||||
static public function driverName(): string {
|
public static function driverName(): string {
|
||||||
return "Mock External Driver";
|
return "Mock External Driver";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function driverFunctions(string $function = null) {
|
public function driverFunctions(string $function = null) {
|
||||||
if($function===null) return $this->functions;
|
if ($function===null) {
|
||||||
|
return $this->functions;
|
||||||
|
}
|
||||||
if (array_key_exists($function, $this->functions)) {
|
if (array_key_exists($function, $this->functions)) {
|
||||||
return $this->functions[$function];
|
return $this->functions[$function];
|
||||||
} else {
|
} else {
|
||||||
|
@ -38,29 +40,41 @@ class DriverExternalMock extends DriverSkeleton implements Driver {
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function auth(string $user, string $password): bool {
|
public function auth(string $user, string $password): bool {
|
||||||
if(!$this->userExists($user)) return false;
|
if (!$this->userExists($user)) {
|
||||||
if($password==="" && $this->db[$user]['password']==="") return true;
|
return false;
|
||||||
if(password_verify($password, $this->db[$user]['password'])) return true;
|
}
|
||||||
|
if ($password==="" && $this->db[$user]['password']==="") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (password_verify($password, $this->db[$user]['password'])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function userExists(string $user): bool {
|
public function userExists(string $user): bool {
|
||||||
return parent::userExists($user);
|
return parent::userExists($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userAdd(string $user, string $password = null): string {
|
public function userAdd(string $user, string $password = null): string {
|
||||||
if($this->userExists($user)) throw new Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]);
|
if ($this->userExists($user)) {
|
||||||
if($password===null) $password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
throw new Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if ($password===null) {
|
||||||
|
$password = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
||||||
|
}
|
||||||
return parent::userAdd($user, $password);
|
return parent::userAdd($user, $password);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRemove(string $user): bool {
|
public function userRemove(string $user): bool {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
return parent::userRemove($user);
|
return parent::userRemove($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userList(string $domain = null): array {
|
public function userList(string $domain = null): array {
|
||||||
if ($domain===null) {
|
if ($domain===null) {
|
||||||
return parent::userList();
|
return parent::userList();
|
||||||
} else {
|
} else {
|
||||||
|
@ -68,30 +82,42 @@ class DriverExternalMock extends DriverSkeleton implements Driver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if (!$this->userExists($user)) {
|
||||||
if($newPassword===null) $newPassword = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
|
if ($newPassword===null) {
|
||||||
|
$newPassword = (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
||||||
|
}
|
||||||
return parent::userPasswordSet($user, $newPassword);
|
return parent::userPasswordSet($user, $newPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPropertiesGet(string $user): array {
|
public function userPropertiesGet(string $user): array {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
return parent::userPropertiesGet($user);
|
return parent::userPropertiesGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPropertiesSet(string $user, array $properties): array {
|
public function userPropertiesSet(string $user, array $properties): array {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
parent::userPropertiesSet($user, $properties);
|
parent::userPropertiesSet($user, $properties);
|
||||||
return $this->userPropertiesGet($user);
|
return $this->userPropertiesGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsGet(string $user): int {
|
public function userRightsGet(string $user): int {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
return parent::userRightsGet($user);
|
return parent::userRightsGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsSet(string $user, int $level): bool {
|
public function userRightsSet(string $user, int $level): bool {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if (!$this->userExists($user)) {
|
||||||
|
throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
}
|
||||||
return parent::userRightsSet($user, $level);
|
return parent::userRightsSet($user, $level);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\User;
|
namespace JKingWeb\Arsse\Test\User;
|
||||||
|
|
||||||
use JKingWeb\Arsse\User\Driver;
|
use JKingWeb\Arsse\User\Driver;
|
||||||
|
|
||||||
class DriverInternalMock extends Database implements Driver {
|
class DriverInternalMock extends Database implements Driver {
|
||||||
|
|
||||||
public $db = [];
|
public $db = [];
|
||||||
protected $functions = [
|
protected $functions = [
|
||||||
"auth" => Driver::FUNC_INTERNAL,
|
"auth" => Driver::FUNC_INTERNAL,
|
||||||
|
@ -19,12 +19,14 @@ class DriverInternalMock extends Database implements Driver {
|
||||||
"userRightsSet" => Driver::FUNC_INTERNAL,
|
"userRightsSet" => Driver::FUNC_INTERNAL,
|
||||||
];
|
];
|
||||||
|
|
||||||
static public function driverName(): string {
|
public static function driverName(): string {
|
||||||
return "Mock Internal Driver";
|
return "Mock Internal Driver";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function driverFunctions(string $function = null) {
|
public function driverFunctions(string $function = null) {
|
||||||
if($function===null) return $this->functions;
|
if ($function===null) {
|
||||||
|
return $this->functions;
|
||||||
|
}
|
||||||
if (array_key_exists($function, $this->functions)) {
|
if (array_key_exists($function, $this->functions)) {
|
||||||
return $this->functions[$function];
|
return $this->functions[$function];
|
||||||
} else {
|
} else {
|
||||||
|
@ -35,10 +37,16 @@ class DriverInternalMock extends Database implements Driver {
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function auth(string $user, string $password): bool {
|
public function auth(string $user, string $password): bool {
|
||||||
if(!$this->userExists($user)) return false;
|
if (!$this->userExists($user)) {
|
||||||
if($password==="" && $this->db[$user]['password']==="") return true;
|
return false;
|
||||||
if(password_verify($password, $this->db[$user]['password'])) return true;
|
}
|
||||||
|
if ($password==="" && $this->db[$user]['password']==="") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (password_verify($password, $this->db[$user]['password'])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test\User;
|
namespace JKingWeb\Arsse\Test\User;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Lang;
|
use JKingWeb\Arsse\Lang;
|
||||||
use JKingWeb\Arsse\User\Driver;
|
use JKingWeb\Arsse\User\Driver;
|
||||||
use JKingWeb\Arsse\User\Exception;
|
use JKingWeb\Arsse\User\Exception;
|
||||||
|
@ -8,14 +9,13 @@ use JKingWeb\Arsse\User\ExceptionAuthz;
|
||||||
use PasswordGenerator\Generator as PassGen;
|
use PasswordGenerator\Generator as PassGen;
|
||||||
|
|
||||||
abstract class DriverSkeleton {
|
abstract class DriverSkeleton {
|
||||||
|
|
||||||
protected $db = [];
|
protected $db = [];
|
||||||
|
|
||||||
function userExists(string $user): bool {
|
public function userExists(string $user): bool {
|
||||||
return array_key_exists($user, $this->db);
|
return array_key_exists($user, $this->db);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userAdd(string $user, string $password = null): string {
|
public function userAdd(string $user, string $password = null): string {
|
||||||
$u = [
|
$u = [
|
||||||
'password' => $password ? password_hash($password, \PASSWORD_DEFAULT) : "",
|
'password' => $password ? password_hash($password, \PASSWORD_DEFAULT) : "",
|
||||||
'rights' => Driver::RIGHTS_NONE,
|
'rights' => Driver::RIGHTS_NONE,
|
||||||
|
@ -24,12 +24,12 @@ abstract class DriverSkeleton {
|
||||||
return $password;
|
return $password;
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRemove(string $user): bool {
|
public function userRemove(string $user): bool {
|
||||||
unset($this->db[$user]);
|
unset($this->db[$user]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function userList(string $domain = null): array {
|
public function userList(string $domain = null): array {
|
||||||
$list = array_keys($this->db);
|
$list = array_keys($this->db);
|
||||||
if ($domain===null) {
|
if ($domain===null) {
|
||||||
return $list;
|
return $list;
|
||||||
|
@ -42,26 +42,26 @@ abstract class DriverSkeleton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
public function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
||||||
$this->db[$user]['password'] = password_hash($newPassword, \PASSWORD_DEFAULT);
|
$this->db[$user]['password'] = password_hash($newPassword, \PASSWORD_DEFAULT);
|
||||||
return $newPassword;
|
return $newPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPropertiesGet(string $user): array {
|
public function userPropertiesGet(string $user): array {
|
||||||
$out = $this->db[$user];
|
$out = $this->db[$user];
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPropertiesSet(string $user, array $properties): array {
|
public function userPropertiesSet(string $user, array $properties): array {
|
||||||
$this->db[$user] = array_merge($this->db[$user], $properties);
|
$this->db[$user] = array_merge($this->db[$user], $properties);
|
||||||
return $this->userPropertiesGet($user);
|
return $this->userPropertiesGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsGet(string $user): int {
|
public function userRightsGet(string $user): int {
|
||||||
return $this->db[$user]['rights'];
|
return $this->db[$user]['rights'];
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsSet(string $user, int $level): bool {
|
public function userRightsSet(string $user, int $level): bool {
|
||||||
$this->db[$user]['rights'] = $level;
|
$this->db[$user]['rights'] = $level;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
require_once __DIR__."/../bootstrap.php";
|
require_once __DIR__."/../bootstrap.php";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -55,10 +56,14 @@ http_response_code((int) $response['code']);
|
||||||
// if the response has a body, set the content type and (possibly) the ETag.
|
// if the response has a body, set the content type and (possibly) the ETag.
|
||||||
if (strlen($response['content'])) {
|
if (strlen($response['content'])) {
|
||||||
header("Content-Type: ".$response['mime']);
|
header("Content-Type: ".$response['mime']);
|
||||||
if($response['cache']) header('ETag: "'.md5($response['content']).'"');
|
if ($response['cache']) {
|
||||||
|
header('ETag: "'.md5($response['content']).'"');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if caching is enabled, set the last-modified date
|
// if caching is enabled, set the last-modified date
|
||||||
if($response['cache']) header("Last-Modified: ".gmdate("D, d M Y H:i:s \G\M\T", $response['lastMod']));
|
if ($response['cache']) {
|
||||||
|
header("Last-Modified: ".gmdate("D, d M Y H:i:s \G\M\T", $response['lastMod']));
|
||||||
|
}
|
||||||
// set any other specified fields verbatim
|
// set any other specified fields verbatim
|
||||||
foreach ($response['fields'] as $h) {
|
foreach ($response['fields'] as $h) {
|
||||||
header($h);
|
header($h);
|
||||||
|
|
Loading…
Reference in a new issue