mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
Consolidate object factoriesinto one place
This commit is contained in:
parent
a0d563e468
commit
54a6fcc0d6
13 changed files with 66 additions and 56 deletions
|
@ -7,8 +7,10 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\Arsse;
|
||||
|
||||
class Arsse {
|
||||
public const VERSION = "0.8.5";
|
||||
public const VERSION = "0.9.0";
|
||||
|
||||
/** @var Factory */
|
||||
public static $obj;
|
||||
/** @var Lang */
|
||||
public static $lang;
|
||||
/** @var Conf */
|
||||
|
@ -19,6 +21,7 @@ class Arsse {
|
|||
public static $user;
|
||||
|
||||
public static function load(Conf $conf): void {
|
||||
static::$obj = static::$obj ?? new Factory;
|
||||
static::$lang = static::$lang ?? new Lang;
|
||||
static::$conf = $conf;
|
||||
static::$lang->set($conf->lang);
|
||||
|
|
21
lib/CLI.php
21
lib/CLI.php
|
@ -182,26 +182,26 @@ USAGE_TEXT;
|
|||
echo Arsse::VERSION.\PHP_EOL;
|
||||
return 0;
|
||||
case "daemon":
|
||||
$this->getInstance(Service::class)->watch(true);
|
||||
Arsse::$obj->get(Service::class)->watch(true);
|
||||
return 0;
|
||||
case "feed refresh":
|
||||
return (int) !Arsse::$db->feedUpdate((int) $args['<n>'], true);
|
||||
case "feed refresh-all":
|
||||
$this->getInstance(Service::class)->watch(false);
|
||||
Arsse::$obj->get(Service::class)->watch(false);
|
||||
return 0;
|
||||
case "conf save-defaults":
|
||||
$file = $this->resolveFile($args['<file>'], "w");
|
||||
return (int) !$this->getInstance(Conf::class)->exportFile($file, true);
|
||||
return (int) !Arsse::$obj->get(Conf::class)->exportFile($file, true);
|
||||
case "user":
|
||||
return $this->userManage($args);
|
||||
case "export":
|
||||
$u = $args['<username>'];
|
||||
$file = $this->resolveFile($args['<file>'], "w");
|
||||
return (int) !$this->getInstance(OPML::class)->exportFile($file, $u, ($args['--flat'] || $args['-f']));
|
||||
return (int) !Arsse::$obj->get(OPML::class)->exportFile($file, $u, ($args['--flat'] || $args['-f']));
|
||||
case "import":
|
||||
$u = $args['<username>'];
|
||||
$file = $this->resolveFile($args['<file>'], "r");
|
||||
return (int) !$this->getInstance(OPML::class)->importFile($file, $u, ($args['--flat'] || $args['-f']), ($args['--replace'] || $args['-r']));
|
||||
return (int) !Arsse::$obj->get(OPML::class)->importFile($file, $u, ($args['--flat'] || $args['-f']), ($args['--replace'] || $args['-r']));
|
||||
}
|
||||
} catch (AbstractException $e) {
|
||||
$this->logError($e->getMessage());
|
||||
|
@ -214,11 +214,6 @@ USAGE_TEXT;
|
|||
fwrite(STDERR, $msg.\PHP_EOL);
|
||||
}
|
||||
|
||||
/** @codeCoverageIgnore */
|
||||
protected function getInstance(string $class) {
|
||||
return new $class;
|
||||
}
|
||||
|
||||
protected function userManage($args): int {
|
||||
$cmd = $this->command(["add", "remove", "set-pass", "unset-pass", "list", "auth"], $args);
|
||||
switch ($cmd) {
|
||||
|
@ -226,7 +221,7 @@ USAGE_TEXT;
|
|||
return $this->userAddOrSetPassword("add", $args["<username>"], $args["<password>"]);
|
||||
case "set-pass":
|
||||
if ($args['--fever']) {
|
||||
$passwd = $this->getInstance(Fever::class)->register($args["<username>"], $args["<password>"]);
|
||||
$passwd = Arsse::$obj->get(Fever::class)->register($args["<username>"], $args["<password>"]);
|
||||
if (is_null($args["<password>"])) {
|
||||
echo $passwd.\PHP_EOL;
|
||||
}
|
||||
|
@ -237,7 +232,7 @@ USAGE_TEXT;
|
|||
// no break
|
||||
case "unset-pass":
|
||||
if ($args['--fever']) {
|
||||
$this->getInstance(Fever::class)->unregister($args["<username>"]);
|
||||
Arsse::$obj->get(Fever::class)->unregister($args["<username>"]);
|
||||
} else {
|
||||
Arsse::$user->passwordUnset($args["<username>"], $args["--oldpass"]);
|
||||
}
|
||||
|
@ -271,7 +266,7 @@ USAGE_TEXT;
|
|||
}
|
||||
|
||||
protected function userAuthenticate(string $user, string $password, bool $fever = false): int {
|
||||
$result = $fever ? $this->getInstance(Fever::class)->authenticate($user, $password) : Arsse::$user->auth($user, $password);
|
||||
$result = $fever ? Arsse::$obj->get(Fever::class)->authenticate($user, $password) : Arsse::$user->auth($user, $password);
|
||||
if ($result) {
|
||||
echo Arsse::$lang->msg("CLI.Auth.Success").\PHP_EOL;
|
||||
return 0;
|
||||
|
|
13
lib/Factory.php
Normal file
13
lib/Factory.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
/** @license MIT
|
||||
* Copyright 2017 J. King, Dustin Wilson et al.
|
||||
* See LICENSE and AUTHORS files for details */
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
class Factory {
|
||||
public function get(string $class) {
|
||||
return new $class;
|
||||
}
|
||||
}
|
|
@ -90,7 +90,7 @@ class REST {
|
|||
// modify the request to have an uppercase method and a stripped target
|
||||
$req = $req->withMethod(strtoupper($req->getMethod()))->withRequestTarget($target);
|
||||
// fetch the correct handler
|
||||
$drv = $this->getHandler($class);
|
||||
$drv = Arsse::$obj->get($class);
|
||||
// generate a response
|
||||
if ($req->getMethod() === "HEAD") {
|
||||
// if the request is a HEAD request, we act exactly as if it were a GET request, and simply remove the response body later
|
||||
|
@ -105,11 +105,6 @@ class REST {
|
|||
return $this->normalizeResponse($res, $req);
|
||||
}
|
||||
|
||||
public function getHandler(string $className): REST\Handler {
|
||||
// instantiate the API handler
|
||||
return new $className();
|
||||
}
|
||||
|
||||
public function apiMatch(string $url): array {
|
||||
$map = $this->apis;
|
||||
// sort the API list so the longest URL prefixes come first
|
||||
|
|
|
@ -16,9 +16,8 @@ abstract class AbstractHandler implements Handler {
|
|||
abstract public function __construct();
|
||||
abstract public function dispatch(ServerRequestInterface $req): ResponseInterface;
|
||||
|
||||
/** @codeCoverageIgnore */
|
||||
protected function now(): \DateTimeImmutable {
|
||||
return Date::normalize("now");
|
||||
return Arsse::$obj->get(\DateTimeImmutable::class)->setTimezone(new \DateTimeZone("UTC"));
|
||||
}
|
||||
|
||||
protected function isAdmin(): bool {
|
||||
|
|
|
@ -214,11 +214,6 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
public function __construct() {
|
||||
}
|
||||
|
||||
/** @codeCoverageIgnore */
|
||||
protected function getInstance(string $class) {
|
||||
return new $class;
|
||||
}
|
||||
|
||||
protected function authenticate(ServerRequestInterface $req): bool {
|
||||
// first check any tokens; this is what Miniflux does
|
||||
if ($req->hasHeader("X-Auth-Token")) {
|
||||
|
@ -1183,7 +1178,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
|
||||
protected function opmlImport(string $data): ResponseInterface {
|
||||
try {
|
||||
$this->getInstance(OPML::class)->import(Arsse::$user->id, $data);
|
||||
Arsse::$obj->get(OPML::class)->import(Arsse::$user->id, $data);
|
||||
} catch (ImportException $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 10611:
|
||||
|
@ -1204,7 +1199,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
|
||||
protected function opmlExport(): ResponseInterface {
|
||||
return new GenericResponse($this->getInstance(OPML::class)->export(Arsse::$user->id), 200, ['Content-Type' => "application/xml"]);
|
||||
return new GenericResponse(Arsse::$obj->get(OPML::class)->export(Arsse::$user->id), 200, ['Content-Type' => "application/xml"]);
|
||||
}
|
||||
|
||||
public static function tokenGenerate(string $user, string $label): string {
|
||||
|
|
|
@ -60,22 +60,20 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function testStartTheDaemon(): void {
|
||||
$srv = \Phake::mock(Service::class);
|
||||
\Phake::when(Arsse::$obj)->get(Service::class)->thenReturn($srv);
|
||||
\Phake::when($srv)->watch->thenReturn(new \DateTimeImmutable);
|
||||
\Phake::when($this->cli)->getInstance(Service::class)->thenReturn($srv);
|
||||
$this->assertConsole($this->cli, "arsse.php daemon", 0);
|
||||
\Phake::verify($this->cli)->loadConf;
|
||||
\Phake::verify($srv)->watch(true);
|
||||
\Phake::verify($this->cli)->getInstance(Service::class);
|
||||
}
|
||||
|
||||
public function testRefreshAllFeeds(): void {
|
||||
$srv = \Phake::mock(Service::class);
|
||||
\Phake::when(Arsse::$obj)->get(Service::class)->thenReturn($srv);
|
||||
\Phake::when($srv)->watch->thenReturn(new \DateTimeImmutable);
|
||||
\Phake::when($this->cli)->getInstance(Service::class)->thenReturn($srv);
|
||||
$this->assertConsole($this->cli, "arsse.php feed refresh-all", 0);
|
||||
\Phake::verify($this->cli)->loadConf;
|
||||
\Phake::verify($srv)->watch(false);
|
||||
\Phake::verify($this->cli)->getInstance(Service::class);
|
||||
}
|
||||
|
||||
/** @dataProvider provideFeedUpdates */
|
||||
|
@ -98,10 +96,10 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
/** @dataProvider provideDefaultConfigurationSaves */
|
||||
public function testSaveTheDefaultConfiguration(string $cmd, int $exitStatus, string $file): void {
|
||||
$conf = \Phake::mock(Conf::class);
|
||||
\Phake::when(Arsse::$obj)->get(Conf::class)->thenReturn($conf);
|
||||
\Phake::when($conf)->exportFile("php://output", true)->thenReturn(true);
|
||||
\Phake::when($conf)->exportFile("good.conf", true)->thenReturn(true);
|
||||
\Phake::when($conf)->exportFile("bad.conf", true)->thenThrow(new \JKingWeb\Arsse\Conf\Exception("fileUnwritable"));
|
||||
\Phake::when($this->cli)->getInstance(Conf::class)->thenReturn($conf);
|
||||
$this->assertConsole($this->cli, $cmd, $exitStatus);
|
||||
\Phake::verify($this->cli, \Phake::times(0))->loadConf;
|
||||
\Phake::verify($conf)->exportFile($file, true);
|
||||
|
@ -169,10 +167,10 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
;
|
||||
}));
|
||||
$fever = \Phake::mock(FeverUser::class);
|
||||
\Phake::when(Arsse::$obj)->get(FeverUser::class)->thenReturn($fever);
|
||||
\Phake::when($fever)->authenticate->thenReturn(false);
|
||||
\Phake::when($fever)->authenticate("john.doe@example.com", "ashalla")->thenReturn(true);
|
||||
\Phake::when($fever)->authenticate("jane.doe@example.com", "thx1138")->thenReturn(true);
|
||||
\Phake::when($this->cli)->getInstance(FeverUser::class)->thenReturn($fever);
|
||||
$this->assertConsole($this->cli, $cmd, $exitStatus, $output);
|
||||
}
|
||||
|
||||
|
@ -226,8 +224,8 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Arsse::$user = $this->createMock(User::class);
|
||||
Arsse::$user->method("passwordSet")->will($this->returnCallback($passwordChange));
|
||||
$fever = \Phake::mock(FeverUser::class);
|
||||
\Phake::when(Arsse::$obj)->get(FeverUser::class)->thenReturn($fever);
|
||||
\Phake::when($fever)->register->thenReturnCallback($passwordChange);
|
||||
\Phake::when($this->cli)->getInstance(FeverUser::class)->thenReturn($fever);
|
||||
$this->assertConsole($this->cli, $cmd, $exitStatus, $output);
|
||||
}
|
||||
|
||||
|
@ -256,8 +254,8 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Arsse::$user = $this->createMock(User::class);
|
||||
Arsse::$user->method("passwordUnset")->will($this->returnCallback($passwordClear));
|
||||
$fever = \Phake::mock(FeverUser::class);
|
||||
\Phake::when(Arsse::$obj)->get(FeverUser::class)->thenReturn($fever);
|
||||
\Phake::when($fever)->unregister->thenReturnCallback($passwordClear);
|
||||
\Phake::when($this->cli)->getInstance(FeverUser::class)->thenReturn($fever);
|
||||
$this->assertConsole($this->cli, $cmd, $exitStatus, $output);
|
||||
}
|
||||
|
||||
|
@ -273,10 +271,10 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
/** @dataProvider provideOpmlExports */
|
||||
public function testExportToOpml(string $cmd, int $exitStatus, string $file, string $user, bool $flat): void {
|
||||
$opml = \Phake::mock(OPML::class);
|
||||
\Phake::when(Arsse::$obj)->get(OPML::class)->thenReturn($opml);
|
||||
\Phake::when($opml)->exportFile("php://output", $user, $flat)->thenReturn(true);
|
||||
\Phake::when($opml)->exportFile("good.opml", $user, $flat)->thenReturn(true);
|
||||
\Phake::when($opml)->exportFile("bad.opml", $user, $flat)->thenThrow(new \JKingWeb\Arsse\ImportExport\Exception("fileUnwritable"));
|
||||
\Phake::when($this->cli)->getInstance(OPML::class)->thenReturn($opml);
|
||||
$this->assertConsole($this->cli, $cmd, $exitStatus);
|
||||
\Phake::verify($this->cli)->loadConf;
|
||||
\Phake::verify($opml)->exportFile($file, $user, $flat);
|
||||
|
@ -314,10 +312,10 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
/** @dataProvider provideOpmlImports */
|
||||
public function testImportFromOpml(string $cmd, int $exitStatus, string $file, string $user, bool $flat, bool $replace): void {
|
||||
$opml = \Phake::mock(OPML::class);
|
||||
\Phake::when(Arsse::$obj)->get(OPML::class)->thenReturn($opml);
|
||||
\Phake::when($opml)->importFile("php://input", $user, $flat, $replace)->thenReturn(true);
|
||||
\Phake::when($opml)->importFile("good.opml", $user, $flat, $replace)->thenReturn(true);
|
||||
\Phake::when($opml)->importFile("bad.opml", $user, $flat, $replace)->thenThrow(new \JKingWeb\Arsse\ImportExport\Exception("fileUnreadable"));
|
||||
\Phake::when($this->cli)->getInstance(OPML::class)->thenReturn($opml);
|
||||
$this->assertConsole($this->cli, $cmd, $exitStatus);
|
||||
\Phake::verify($this->cli)->loadConf;
|
||||
\Phake::verify($opml)->importFile($file, $user, $flat, $replace);
|
||||
|
|
17
tests/cases/Misc/TestFactory.php
Normal file
17
tests/cases/Misc/TestFactory.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/** @license MIT
|
||||
* Copyright 2017 J. King, Dustin Wilson et al.
|
||||
* See LICENSE and AUTHORS files for details */
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\TestCase\Misc;
|
||||
|
||||
use JKingWeb\Arsse\Factory;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\Factory */
|
||||
class TestFactory extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
public function testInstantiateAClass(): void {
|
||||
$f = new Factory;
|
||||
$this->assertInstanceOf(\stdClass::class, $f->get(\stdClass::class));
|
||||
}
|
||||
}
|
|
@ -211,8 +211,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
throw $u[2];
|
||||
}
|
||||
});
|
||||
$this->h = $this->createPartialMock(V1::class, ["now"]);
|
||||
$this->h->method("now")->willReturn(Date::normalize(self::NOW));
|
||||
\Phake::when(Arsse::$obj)->get(\DateTimeImmutable::class)->thenReturn(new \DateTimeImmutable(self::NOW));
|
||||
$this->assertMessage($exp, $this->req("GET", $route, "", [], $user));
|
||||
}
|
||||
|
||||
|
@ -240,8 +239,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
/** @dataProvider provideUserModifications */
|
||||
public function testModifyAUser(bool $admin, string $url, array $body, $in1, $out1, $in2, $out2, $in3, $out3, ResponseInterface $exp): void {
|
||||
$this->h = $this->createPartialMock(V1::class, ["now"]);
|
||||
$this->h->method("now")->willReturn(Date::normalize(self::NOW));
|
||||
\Phake::when(Arsse::$obj)->get(\DateTimeImmutable::class)->thenReturn(new \DateTimeImmutable(self::NOW));
|
||||
Arsse::$user = $this->createMock(User::class);
|
||||
Arsse::$user->method("begin")->willReturn($this->transaction);
|
||||
Arsse::$user->method("propertiesGet")->willReturnCallback(function(string $u, bool $includeLarge) use ($admin) {
|
||||
|
@ -321,8 +319,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
/** @dataProvider provideUserAdditions */
|
||||
public function testAddAUser(array $body, $in1, $out1, $in2, $out2, ResponseInterface $exp): void {
|
||||
$this->h = $this->createPartialMock(V1::class, ["now"]);
|
||||
$this->h->method("now")->willReturn(Date::normalize(self::NOW));
|
||||
\Phake::when(Arsse::$obj)->get(\DateTimeImmutable::class)->thenReturn(new \DateTimeImmutable(self::NOW));
|
||||
Arsse::$user = $this->createMock(User::class);
|
||||
Arsse::$user->method("begin")->willReturn($this->transaction);
|
||||
Arsse::$user->method("propertiesGet")->willReturnCallback(function(string $u, bool $includeLarge) {
|
||||
|
|
|
@ -286,14 +286,6 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
];
|
||||
}
|
||||
|
||||
public function testCreateHandlers(): void {
|
||||
$r = new REST();
|
||||
foreach (REST::API_LIST as $api) {
|
||||
$class = $api['class'];
|
||||
$this->assertInstanceOf(Handler::class, $r->getHandler($class));
|
||||
}
|
||||
}
|
||||
|
||||
/** @dataProvider provideMockRequests */
|
||||
public function testDispatchRequests(ServerRequest $req, string $method, bool $called, string $class = "", string $target = ""): void {
|
||||
$r = \Phake::partialMock(REST::class);
|
||||
|
@ -305,7 +297,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
});
|
||||
if ($called) {
|
||||
$h = \Phake::mock($class);
|
||||
\Phake::when($r)->getHandler($class)->thenReturn($h);
|
||||
\Phake::when(Arsse::$obj)->get($class)->thenReturn($h);
|
||||
\Phake::when($h)->dispatch->thenReturn(new EmptyResponse(204));
|
||||
}
|
||||
$out = $r->dispatch($req);
|
||||
|
|
|
@ -1700,8 +1700,7 @@ LONG_STRING;
|
|||
public function testRetrieveHeadlines(bool $full, array $in, $out, Context $c, array $fields, array $order, ResponseInterface $exp): void {
|
||||
$base = ['op' => $full ? "getHeadlines" : "getCompactHeadlines", 'sid' => "PriestsOfSyrinx"];
|
||||
$in = array_merge($base, $in);
|
||||
$this->h = \Phake::partialMock(API::class);
|
||||
\Phake::when($this->h)->now->thenReturn(Date::normalize(self::NOW));
|
||||
\Phake::when(Arsse::$obj)->get(\DateTimeImmutable::class)->thenReturn(new \DateTimeImmutable(self::NOW));
|
||||
\Phake::when(Arsse::$db)->labelList->thenReturn(new Result($this->v($this->labels)));
|
||||
\Phake::when(Arsse::$db)->labelList($this->anything(), false)->thenReturn(new Result($this->v($this->usedLabels)));
|
||||
\Phake::when(Arsse::$db)->articleLabelsGet->thenReturn([]);
|
||||
|
|
|
@ -13,6 +13,7 @@ use JKingWeb\Arsse\Arsse;
|
|||
use JKingWeb\Arsse\Conf;
|
||||
use JKingWeb\Arsse\Db\Driver;
|
||||
use JKingWeb\Arsse\Db\Result;
|
||||
use JKingWeb\Arsse\Factory;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\ValueInfo;
|
||||
use JKingWeb\Arsse\Misc\URL;
|
||||
|
@ -45,6 +46,11 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
|||
}
|
||||
if ($loadLang) {
|
||||
Arsse::$lang = new \JKingWeb\Arsse\Lang();
|
||||
// also create the object factory as a mock
|
||||
Arsse::$obj = \Phake::mock(Factory::class);
|
||||
\Phake::when(Arsse::$obj)->get->thenReturnCallback(function(string $class) {
|
||||
return new $class;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
<file>cases/Conf/TestConf.php</file>
|
||||
</testsuite>
|
||||
<testsuite name="Sundry">
|
||||
<file>cases/Misc/TestFactory.php</file>
|
||||
<file>cases/Misc/TestValueInfo.php</file>
|
||||
<file>cases/Misc/TestDate.php</file>
|
||||
<file>cases/Misc/TestQuery.php</file>
|
||||
|
|
Loading…
Reference in a new issue