mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
Changed "NewsSync" to "Arsse"
This commit is contained in:
parent
9d5dab249c
commit
7236020b8b
68 changed files with 316 additions and 316 deletions
88
.gitignore
vendored
88
.gitignore
vendored
|
@ -1,44 +1,44 @@
|
|||
#dependencies
|
||||
vendor
|
||||
|
||||
#temp files
|
||||
cache/*
|
||||
newssync.db*
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
||||
# OSX
|
||||
# =========================
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must ends with two \r.
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear on external disk
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
#dependencies
|
||||
vendor
|
||||
|
||||
#temp files
|
||||
cache/*
|
||||
arsse.db*
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
||||
# OSX
|
||||
# =========================
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must ends with two \r.
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear on external disk
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
const BASE = __DIR__.DIRECTORY_SEPARATOR;
|
||||
const NS_BASE = __NAMESPACE__."\\";
|
||||
|
|
|
@ -32,12 +32,12 @@
|
|||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"JKingWeb\\NewsSync\\": "lib/"
|
||||
"JKingWeb\\Arsse\\": "lib/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"JKingWeb\\NewsSync\\Test\\": "tests/lib/"
|
||||
"JKingWeb\\Arsse\\Test\\": "tests/lib/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
abstract class AbstractException extends \Exception {
|
||||
|
||||
|
|
12
lib/Conf.php
12
lib/Conf.php
|
@ -1,27 +1,27 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
class Conf {
|
||||
public $lang = "en";
|
||||
|
||||
public $dbDriver = Db\SQLite3\Driver::class;
|
||||
public $dbSchemaBase = BASE.'sql';
|
||||
public $dbSQLite3File = BASE."newssync.db";
|
||||
public $dbSQLite3File = BASE."arsse.db";
|
||||
public $dbSQLite3Key = "";
|
||||
public $dbSQLite3AutoUpd = true;
|
||||
public $dbPostgreSQLHost = "localhost";
|
||||
public $dbPostgreSQLUser = "newssync";
|
||||
public $dbPostgreSQLUser = "arsse";
|
||||
public $dbPostgreSQLPass = "";
|
||||
public $dbPostgreSQLPort = 5432;
|
||||
public $dbPostgreSQLDb = "newssync";
|
||||
public $dbPostgreSQLDb = "arsse";
|
||||
public $dbPostgreSQLSchema = "";
|
||||
public $dbPostgreSQLAutoUpd = false;
|
||||
public $dbMySQLHost = "localhost";
|
||||
public $dbMySQLUser = "newssync";
|
||||
public $dbMySQLUser = "arsse";
|
||||
public $dbMySQLPass = "";
|
||||
public $dbMySQLPort = 3306;
|
||||
public $dbMySQLDb = "newssync";
|
||||
public $dbMySQLDb = "arsse";
|
||||
public $dbMySQLAutoUpd = false;
|
||||
|
||||
public $userDriver = User\Internal\Driver::class;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Conf;
|
||||
namespace JKingWeb\Arsse\Conf;
|
||||
|
||||
class Exception extends \JKingWeb\NewsSync\AbstractException {
|
||||
class Exception extends \JKingWeb\Arsse\AbstractException {
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
use PasswordGenerator\Generator as PassGen;
|
||||
|
||||
class Database {
|
||||
|
@ -50,7 +50,7 @@ class Database {
|
|||
}
|
||||
|
||||
public function settingGet(string $key) {
|
||||
$row = $this->db->prepare("SELECT value, type from newssync_settings where key = ?", "str")->run($key)->getRow();
|
||||
$row = $this->db->prepare("SELECT value, type from arsse_settings where key = ?", "str")->run($key)->getRow();
|
||||
if(!$row) return null;
|
||||
switch($row['type']) {
|
||||
case "int": return (int) $row['value'];
|
||||
|
@ -157,17 +157,17 @@ class Database {
|
|||
$value = $in;
|
||||
break;
|
||||
}
|
||||
return (bool) $this->db->prepare("REPLACE INTO newssync_settings(key,value,type) values(?,?,?)", "str", "str", "str")->run($key, $value, $type)->changes();
|
||||
return (bool) $this->db->prepare("REPLACE INTO arsse_settings(key,value,type) values(?,?,?)", "str", "str", "str")->run($key, $value, $type)->changes();
|
||||
}
|
||||
|
||||
public function settingRemove(string $key): bool {
|
||||
$this->db->prepare("DELETE from newssync_settings where key is ?", "str")->run($key);
|
||||
$this->db->prepare("DELETE from arsse_settings where key is ?", "str")->run($key);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function userExists(string $user): bool {
|
||||
if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
return (bool) $this->db->prepare("SELECT count(*) from newssync_users where id is ?", "str")->run($user)->getValue();
|
||||
return (bool) $this->db->prepare("SELECT count(*) from arsse_users where id is ?", "str")->run($user)->getValue();
|
||||
}
|
||||
|
||||
public function userAdd(string $user, string $password = null): string {
|
||||
|
@ -176,13 +176,13 @@ class Database {
|
|||
if($password===null) $password = (new PassGen)->length($this->data->conf->userTempPasswordLength)->get();
|
||||
$hash = "";
|
||||
if(strlen($password) > 0) $hash = password_hash($password, \PASSWORD_DEFAULT);
|
||||
$this->db->prepare("INSERT INTO newssync_users(id,password) values(?,?)", "str", "str")->runArray([$user,$hash]);
|
||||
$this->db->prepare("INSERT INTO arsse_users(id,password) values(?,?)", "str", "str")->runArray([$user,$hash]);
|
||||
return $password;
|
||||
}
|
||||
|
||||
public function userRemove(string $user): bool {
|
||||
if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
if($this->db->prepare("DELETE from newssync_users where id is ?", "str")->run($user)->changes() < 1) throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
if($this->db->prepare("DELETE from arsse_users where id is ?", "str")->run($user)->changes() < 1) throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -191,17 +191,17 @@ class Database {
|
|||
if(!$this->data->user->authorize("@".$domain, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $domain]);
|
||||
$domain = str_replace(["\\","%","_"],["\\\\", "\\%", "\\_"], $domain);
|
||||
$domain = "%@".$domain;
|
||||
return $this->db->prepare("SELECT id from newssync_users where id like ?", "str")->run($domain)->getAll();
|
||||
return $this->db->prepare("SELECT id from arsse_users where id like ?", "str")->run($domain)->getAll();
|
||||
} else {
|
||||
if(!$this->data->user->authorize("", __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => "global"]);
|
||||
return $this->db->prepare("SELECT id from newssync_users")->run()->getAll();
|
||||
return $this->db->prepare("SELECT id from arsse_users")->run()->getAll();
|
||||
}
|
||||
}
|
||||
|
||||
public function userPasswordGet(string $user): string {
|
||||
if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
if(!$this->userExists($user)) throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
return (string) $this->db->prepare("SELECT password from newssync_users where id is ?", "str")->run($user)->getValue();
|
||||
return (string) $this->db->prepare("SELECT password from arsse_users where id is ?", "str")->run($user)->getValue();
|
||||
}
|
||||
|
||||
public function userPasswordSet(string $user, string $password = null): string {
|
||||
|
@ -210,13 +210,13 @@ class Database {
|
|||
if($password===null) $password = (new PassGen)->length($this->data->conf->userTempPasswordLength)->get();
|
||||
$hash = "";
|
||||
if(strlen($password > 0)) $hash = password_hash($password, \PASSWORD_DEFAULT);
|
||||
$this->db->prepare("UPDATE newssync_users set password = ? where id is ?", "str", "str")->run($hash, $user);
|
||||
$this->db->prepare("UPDATE arsse_users set password = ? where id is ?", "str", "str")->run($hash, $user);
|
||||
return $password;
|
||||
}
|
||||
|
||||
public function userPropertiesGet(string $user): array {
|
||||
if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
$prop = $this->db->prepare("SELECT name,rights from newssync_users where id is ?", "str")->run($user)->getRow();
|
||||
$prop = $this->db->prepare("SELECT name,rights from arsse_users where id is ?", "str")->run($user)->getRow();
|
||||
if(!$prop) return [];
|
||||
return $prop;
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ class Database {
|
|||
$this->db->begin();
|
||||
foreach($valid as $prop => $type) {
|
||||
if(!array_key_exists($prop, $properties)) continue;
|
||||
$this->db->prepare("UPDATE newssync_users set $prop = ? where id is ?", $type, "str")->run($properties[$prop], $user);
|
||||
$this->db->prepare("UPDATE arsse_users set $prop = ? where id is ?", $type, "str")->run($properties[$prop], $user);
|
||||
}
|
||||
$this->db->commit();
|
||||
return $this->userPropertiesGet($user);
|
||||
|
@ -238,13 +238,13 @@ class Database {
|
|||
|
||||
public function userRightsGet(string $user): int {
|
||||
if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
return (int) $this->db->prepare("SELECT rights from newssync_users where id is ?", "str")->run($user)->getValue();
|
||||
return (int) $this->db->prepare("SELECT rights from arsse_users where id is ?", "str")->run($user)->getValue();
|
||||
}
|
||||
|
||||
public function userRightsSet(string $user, int $rights): bool {
|
||||
if(!$this->data->user->authorize($user, __FUNCTION__, $rights)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
if(!$this->userExists($user)) return false;
|
||||
$this->db->prepare("UPDATE newssync_users set rights = ? where id is ?", "int", "str")->run($rights, $user);
|
||||
$this->db->prepare("UPDATE arsse_users set rights = ? where id is ?", "int", "str")->run($rights, $user);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -262,7 +262,7 @@ class Database {
|
|||
|
||||
// If the feed doesn't already exist in the database then add it to the database
|
||||
// after determining its validity with PicoFeed.
|
||||
$qFeed = $this->db->prepare("SELECT id from newssync_feeds where url is ? and username is ? and password is ?", "str", "str", "str");
|
||||
$qFeed = $this->db->prepare("SELECT id from arsse_feeds where url is ? and username is ? and password is ?", "str", "str", "str");
|
||||
$feed = $qFeed->run($url, $fetchUser, $fetchPassword)->getValue();
|
||||
if ($feed === null) {
|
||||
$feed = new Feed($url);
|
||||
|
@ -271,7 +271,7 @@ class Database {
|
|||
// Add the feed to the database and return its Id which will be used when adding
|
||||
// its articles to the database.
|
||||
$feedID = $this->db->prepare(
|
||||
'INSERT INTO newssync_feeds(url,title,favicon,source,updated,modified,etag,username,password)
|
||||
'INSERT INTO arsse_feeds(url,title,favicon,source,updated,modified,etag,username,password)
|
||||
values(?,?,?,?,?,?,?,?,?)',
|
||||
'str', 'str', 'str', 'str', 'datetime', 'datetime', 'str', 'str', 'str')->run(
|
||||
$url,
|
||||
|
@ -293,14 +293,14 @@ class Database {
|
|||
}
|
||||
|
||||
// Add the feed to the user's subscriptions.
|
||||
$sub = $this->db->prepare('INSERT INTO newssync_subscriptions(owner,feed) values(?,?)', 'str', 'int')->run($user, $feedID)->lastId();
|
||||
$sub = $this->db->prepare('INSERT INTO arsse_subscriptions(owner,feed) values(?,?)', 'str', 'int')->run($user, $feedID)->lastId();
|
||||
$this->db->commit();
|
||||
return $sub;
|
||||
}
|
||||
|
||||
public function subscriptionRemove(string $user, int $id): bool {
|
||||
if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
return (bool) $this->db->prepare("DELETE from newssync_subscriptions where id is ?", "int")->run($id)->changes();
|
||||
return (bool) $this->db->prepare("DELETE from arsse_subscriptions where id is ?", "int")->run($id)->changes();
|
||||
}
|
||||
|
||||
public function folderAdd(string $user, array $data): int {
|
||||
|
@ -326,7 +326,7 @@ class Database {
|
|||
$root = null;
|
||||
} else {
|
||||
// if a parent is specified, make sure it exists and belongs to the user; get its root (first-level) folder if it's a nested folder
|
||||
$p = $this->db->prepare("SELECT id,root from newssync_folders where owner is ? and id is ?", "str", "int")->run($user, $parent)->getRow();
|
||||
$p = $this->db->prepare("SELECT id,root from arsse_folders where owner is ? and id is ?", "str", "int")->run($user, $parent)->getRow();
|
||||
if(!$p) {
|
||||
throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "parent", 'id' => $parent]);
|
||||
} else {
|
||||
|
@ -336,11 +336,11 @@ class Database {
|
|||
}
|
||||
// check if a folder by the same name already exists, because nulls are wonky in SQL
|
||||
// FIXME: How should folder name be compared? Should a Unicode normalization be applied before comparison and insertion?
|
||||
if($this->db->prepare("SELECT count(*) from newssync_folders where owner is ? and parent is ? and name is ?", "str", "int", "str")->run($user, $parent, $data['name'])->getValue() > 0) {
|
||||
if($this->db->prepare("SELECT count(*) from arsse_folders where owner is ? and parent is ? and name is ?", "str", "int", "str")->run($user, $parent, $data['name'])->getValue() > 0) {
|
||||
throw new Db\ExceptionInput("constraintViolation"); // FIXME: There needs to be a practical message here
|
||||
}
|
||||
// actually perform the insert (!)
|
||||
return $this->db->prepare("INSERT INTO newssync_folders(owner,parent,root,name) values(?,?,?,?)", "str", "int", "int", "str")->run($user, $parent, $root, $data['name'])->lastId();
|
||||
return $this->db->prepare("INSERT INTO arsse_folders(owner,parent,root,name) values(?,?,?,?)", "str", "int", "int", "str")->run($user, $parent, $root, $data['name'])->lastId();
|
||||
}
|
||||
|
||||
public function folderList(string $user, int $parent = null, bool $recursive = true): Db\Result {
|
||||
|
@ -354,11 +354,11 @@ class Database {
|
|||
}
|
||||
// if we're not returning a recursive list we can use a simpler query
|
||||
if(!$recursive) {
|
||||
return $this->db->preparre("SELECT id,name,parent from newssync_folders where owner is ? and parent is ?", "str", "int")->run($user, $parent);
|
||||
return $this->db->preparre("SELECT id,name,parent from arsse_folders where owner is ? and parent is ?", "str", "int")->run($user, $parent);
|
||||
} else {
|
||||
return $this->db->prepare(
|
||||
"WITH RECURSIVE folders(id) as (SELECT id from newssync_folders where owner is ? and parent is ? union select newssync_folders.id from newssync_folders join folders on newssync_folders.parent=folders.id) ".
|
||||
"SELECT id,name,parent from newssync_folders where id in(SELECT id from folders) order by name",
|
||||
"WITH RECURSIVE folders(id) as (SELECT id from arsse_folders where owner is ? and parent is ? union select arsse_folders.id from arsse_folders join folders on arsse_folders.parent=folders.id) ".
|
||||
"SELECT id,name,parent from arsse_folders where id in(SELECT id from folders) order by name",
|
||||
"str", "int")->run($user, $parent);
|
||||
}
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ class Database {
|
|||
public function articleAdd(PicoFeed\Parser\Item $article): int {
|
||||
$this->db->begin();
|
||||
|
||||
$articleId = $this->db->prepare('INSERT INTO newssync_articles(feed,url,title,author,published,edited,guid,content,url_title_hash,url_content_hash,title_content_hash)
|
||||
$articleId = $this->db->prepare('INSERT INTO arsse_articles(feed,url,title,author,published,edited,guid,content,url_title_hash,url_content_hash,title_content_hash)
|
||||
values(?,?,?,?,?,?,?,?,?,?,?)',
|
||||
'int', 'str', 'str', 'str', 'datetime', 'datetime', 'str', 'str', 'str', 'str', 'str')->run(
|
||||
$feedID,
|
||||
|
@ -386,7 +386,7 @@ class Database {
|
|||
$categories = $article->getTag('category');
|
||||
if (count($categories) > 0) {
|
||||
foreach ($categories as $c) {
|
||||
$this->db->prepare('INSERT INTO newssync_tags(article,name) values(?,?)', 'int', 'str')->run($articleId, $c);
|
||||
$this->db->prepare('INSERT INTO arsse_tags(article,name) values(?,?)', 'int', 'str')->run($articleId, $c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -395,7 +395,7 @@ class Database {
|
|||
}
|
||||
|
||||
public function updateFeeds(): int {
|
||||
$feeds = $this->db->query('SELECT id, url, username, password, DATEFORMAT("http", modified) AS lastmodified, etag FROM newssync_feeds')->getAll();
|
||||
$feeds = $this->db->query('SELECT id, url, username, password, DATEFORMAT("http", modified) AS lastmodified, etag FROM arsse_feeds')->getAll();
|
||||
foreach ($feeds as $f) {
|
||||
$feed = new Feed($f['url'], $f['lastmodified'], $f['etag'], $f['username'], $f['password']);
|
||||
// FIXME: What to do if fails? It currently throws an exception which isn't ideal here.
|
||||
|
@ -405,7 +405,7 @@ class Database {
|
|||
$feed->parse();
|
||||
|
||||
$this->db->begin();
|
||||
$articles = $this->db->prepare('SELECT id, url, title, author, DATEFORMAT("http", edited) AS edited_date, guid, content, url_title_hash, url_content_hash, title_content_hash FROM newssync_articles WHERE feed is ? ORDER BY id', 'int')->run($f['id'])->getAll();
|
||||
$articles = $this->db->prepare('SELECT id, url, title, author, DATEFORMAT("http", edited) AS edited_date, guid, content, url_title_hash, url_content_hash, title_content_hash FROM arsse_articles WHERE feed is ? ORDER BY id', 'int')->run($f['id'])->getAll();
|
||||
|
||||
foreach ($feed->data->items as $i) {
|
||||
// Iterate through the articles in the database to determine a match for the one
|
||||
|
@ -449,7 +449,7 @@ class Database {
|
|||
}
|
||||
|
||||
if ($update) {
|
||||
$this->db->prepare('UPDATE newssync_articles SET url = ?, title = ?, author = ?, published = ?, edited = ?, modified = ?, guid = ?, content = ?, url_title_hash = ?, url_content_hash = ?, title_content_hash = ? WHERE id is ?', 'str', 'str', 'str', 'datetime', 'datetime', 'datetime', 'str', 'str', 'str', 'str', 'str', 'int')->run(
|
||||
$this->db->prepare('UPDATE arsse_articles SET url = ?, title = ?, author = ?, published = ?, edited = ?, modified = ?, guid = ?, content = ?, url_title_hash = ?, url_content_hash = ?, title_content_hash = ? WHERE id is ?', 'str', 'str', 'str', 'datetime', 'datetime', 'datetime', 'str', 'str', 'str', 'str', 'str', 'int')->run(
|
||||
$i->url,
|
||||
$i->title,
|
||||
$i->author,
|
||||
|
@ -469,7 +469,7 @@ class Database {
|
|||
}
|
||||
|
||||
// Lastly update the feed database itself with updated information.
|
||||
$this->db->prepare('UPDATE newssync_feeds SET url = ?, title = ?, favicon = ?, source = ?, updated = ?, modified = ?, etag = ? WHERE id is ?', 'str', 'str', 'str', 'str', 'datetime', 'datetime', 'str', 'int')->run(
|
||||
$this->db->prepare('UPDATE arsse_feeds SET url = ?, title = ?, favicon = ?, source = ?, updated = ?, modified = ?, etag = ? WHERE id is ?', 'str', 'str', 'str', 'str', 'datetime', 'datetime', 'str', 'int')->run(
|
||||
$feed->feedUrl,
|
||||
$feed->title,
|
||||
$feed->favicon,
|
||||
|
@ -489,13 +489,13 @@ class Database {
|
|||
public function folderRemove(string $user, int $id): bool {
|
||||
if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
// common table expression to list all descendant folders of the target folder
|
||||
$cte = "RECURSIVE folders(id) as (SELECT id from newssync_folders where owner is ? and id is ? union select newssync_folders.id from newssync_folders join folders on newssync_folders.parent=folders.id) ";
|
||||
$cte = "RECURSIVE folders(id) as (SELECT id from arsse_folders where owner is ? and id is ? union select arsse_folders.id from arsse_folders join folders on arsse_folders.parent=folders.id) ";
|
||||
$changes = 0;
|
||||
$this->db->begin();
|
||||
// first delete any feed subscriptions contained within the folder tree (this may not be necesary because of foreign keys)
|
||||
$changes += $this->db->prepare("WITH $cte"."DELETE FROM newssync_subscriptions where folder in(select id from folders)", "str", "int")->run($user, $id)->changes();
|
||||
$changes += $this->db->prepare("WITH $cte"."DELETE FROM arsse_subscriptions where folder in(select id from folders)", "str", "int")->run($user, $id)->changes();
|
||||
// next delete the folders themselves
|
||||
$changes += $this->db->prepare("WITH $cte"."DELETE FROM newssync_folders where id in(select id from folders)", "str", "int")->run($user, $id)->changes();
|
||||
$changes += $this->db->prepare("WITH $cte"."DELETE FROM arsse_folders where id in(select id from folders)", "str", "int")->run($user, $id)->changes();
|
||||
$this->db->commit();
|
||||
return (bool) $changes;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db;
|
||||
namespace JKingWeb\Arsse\Db;
|
||||
use JKingWeb\DrUUID\UUID as UUID;
|
||||
|
||||
abstract class AbstractDriver implements Driver {
|
||||
|
@ -8,21 +8,21 @@ abstract class AbstractDriver implements Driver {
|
|||
|
||||
public function schemaVersion(): int {
|
||||
try {
|
||||
return (int) $this->query("SELECT value from newssync_settings where key is schema_version")->getValue();
|
||||
return (int) $this->query("SELECT value from arsse_settings where key is schema_version")->getValue();
|
||||
} catch(Exception $e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function begin(): bool {
|
||||
$this->exec("SAVEPOINT newssync_".(++$this->transDepth));
|
||||
$this->exec("SAVEPOINT arsse_".(++$this->transDepth));
|
||||
return true;
|
||||
}
|
||||
|
||||
public function commit(bool $all = false): bool {
|
||||
if($this->transDepth==0) return false;
|
||||
if(!$all) {
|
||||
$this->exec("RELEASE SAVEPOINT newssync_".($this->transDepth--));
|
||||
$this->exec("RELEASE SAVEPOINT arsse_".($this->transDepth--));
|
||||
} else {
|
||||
$this->exec("COMMIT TRANSACTION");
|
||||
$this->transDepth = 0;
|
||||
|
@ -33,9 +33,9 @@ abstract class AbstractDriver implements Driver {
|
|||
public function rollback(bool $all = false): bool {
|
||||
if($this->transDepth==0) return false;
|
||||
if(!$all) {
|
||||
$this->exec("ROLLBACK TRANSACTION TO SAVEPOINT newssync_".($this->transDepth));
|
||||
$this->exec("ROLLBACK TRANSACTION TO SAVEPOINT arsse_".($this->transDepth));
|
||||
// rollback to savepoint does not collpase the savepoint
|
||||
$this->exec("RELEASE SAVEPOINT newssync_".($this->transDepth--));
|
||||
$this->exec("RELEASE SAVEPOINT arsse_".($this->transDepth--));
|
||||
} else {
|
||||
$this->exec("ROLLBACK TRANSACTION");
|
||||
$this->transDepth = 0;
|
||||
|
@ -48,23 +48,23 @@ abstract class AbstractDriver implements Driver {
|
|||
if($this->isLocked()) return false;
|
||||
$uuid = UUID::mintStr();
|
||||
try {
|
||||
$this->prepare("INSERT INTO newssync_settings(key,value) values(?,?)", "str", "str")->run("lock", $uuid);
|
||||
$this->prepare("INSERT INTO arsse_settings(key,value) values(?,?)", "str", "str")->run("lock", $uuid);
|
||||
} catch(ExceptionInput $e) {
|
||||
return false;
|
||||
}
|
||||
sleep(1);
|
||||
return ($this->query("SELECT value from newssync_settings where key is 'lock'")->getValue() == $uuid);
|
||||
return ($this->query("SELECT value from arsse_settings where key is 'lock'")->getValue() == $uuid);
|
||||
}
|
||||
|
||||
public function unlock(): bool {
|
||||
if($this->schemaVersion() < 1) return true;
|
||||
$this->exec("DELETE from newssync_settings where key is 'lock'");
|
||||
$this->exec("DELETE from arsse_settings where key is 'lock'");
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isLocked(): bool {
|
||||
if($this->schemaVersion() < 1) return false;
|
||||
return ($this->query("SELECT count(*) from newssync_settings where key is 'lock'")->getValue() > 0);
|
||||
return ($this->query("SELECT count(*) from arsse_settings where key is 'lock'")->getValue() > 0);
|
||||
}
|
||||
|
||||
public function prepare(string $query, string ...$paramType): Statement {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db;
|
||||
namespace JKingWeb\Arsse\Db;
|
||||
|
||||
abstract class AbstractStatement implements Statement {
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db;
|
||||
namespace JKingWeb\Arsse\Db;
|
||||
|
||||
interface Driver {
|
||||
function __construct(\JKingWeb\NewsSync\RuntimeData $data, bool $install = false);
|
||||
function __construct(\JKingWeb\Arsse\RuntimeData $data, bool $install = false);
|
||||
// returns a human-friendly name for the driver (for display in installer, for example)
|
||||
static function driverName(): string;
|
||||
// returns the version of the scheme of the opened database; if uninitialized should return 0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db;
|
||||
namespace JKingWeb\Arsse\Db;
|
||||
|
||||
class Exception extends \JKingWeb\NewsSync\AbstractException {
|
||||
class Exception extends \JKingWeb\Arsse\AbstractException {
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db;
|
||||
namespace JKingWeb\Arsse\Db;
|
||||
|
||||
class ExceptionInput extends \JKingWeb\NewsSync\AbstractException {
|
||||
class ExceptionInput extends \JKingWeb\Arsse\AbstractException {
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db;
|
||||
namespace JKingWeb\Arsse\Db;
|
||||
|
||||
class ExceptionTimeout extends \JKingWeb\NewsSync\AbstractException {
|
||||
class ExceptionTimeout extends \JKingWeb\Arsse\AbstractException {
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db;
|
||||
namespace JKingWeb\Arsse\Db;
|
||||
|
||||
interface Result extends \Iterator {
|
||||
function current();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db\SQLite3;
|
||||
namespace JKingWeb\Arsse\Db\SQLite3;
|
||||
|
||||
class CustomFunctions {
|
||||
// Converts from SQLite3's date format to a specified standard date format.
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db\SQLite3;
|
||||
use JKingWeb\NewsSync\Lang;
|
||||
use JKingWeb\NewsSync\Db\Exception;
|
||||
use JKingWeb\NewsSync\Db\ExceptionInput;
|
||||
use JKingWeb\NewsSync\Db\ExceptionTimeout;
|
||||
namespace JKingWeb\Arsse\Db\SQLite3;
|
||||
use JKingWeb\Arsse\Lang;
|
||||
use JKingWeb\Arsse\Db\Exception;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Db\ExceptionTimeout;
|
||||
|
||||
|
||||
class Driver extends \JKingWeb\NewsSync\Db\AbstractDriver {
|
||||
class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
|
||||
use ExceptionBuilder;
|
||||
|
||||
const SQLITE_BUSY = 5;
|
||||
|
@ -17,7 +17,7 @@ class Driver extends \JKingWeb\NewsSync\Db\AbstractDriver {
|
|||
protected $db;
|
||||
protected $data;
|
||||
|
||||
public function __construct(\JKingWeb\NewsSync\RuntimeData $data, bool $install = false) {
|
||||
public function __construct(\JKingWeb\Arsse\RuntimeData $data, bool $install = false) {
|
||||
// check to make sure required extension is loaded
|
||||
if(!class_exists("SQLite3")) throw new Exception("extMissing", self::driverName());
|
||||
$this->data = $data;
|
||||
|
@ -115,7 +115,7 @@ class Driver extends \JKingWeb\NewsSync\Db\AbstractDriver {
|
|||
}
|
||||
}
|
||||
|
||||
public function query(string $query): \JKingWeb\NewsSync\Db\Result {
|
||||
public function query(string $query): \JKingWeb\Arsse\Db\Result {
|
||||
try {
|
||||
$r = $this->db->query($query);
|
||||
} catch(\Exception $e) {
|
||||
|
@ -127,7 +127,7 @@ class Driver extends \JKingWeb\NewsSync\Db\AbstractDriver {
|
|||
return new Result($r, [$changes, $lastId]);
|
||||
}
|
||||
|
||||
public function prepareArray(string $query, array $paramTypes): \JKingWeb\NewsSync\Db\Statement {
|
||||
public function prepareArray(string $query, array $paramTypes): \JKingWeb\Arsse\Db\Statement {
|
||||
try {
|
||||
$s = $this->db->prepare($query);
|
||||
} catch(\Exception $e) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db\SQLite3;
|
||||
use JKingWeb\NewsSync\Db\Exception;
|
||||
use JKingWeb\NewsSync\Db\ExceptionInput;
|
||||
use JKingWeb\NewsSync\Db\ExceptionTimeout;
|
||||
namespace JKingWeb\Arsse\Db\SQLite3;
|
||||
use JKingWeb\Arsse\Db\Exception;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Db\ExceptionTimeout;
|
||||
|
||||
|
||||
trait ExceptionBuilder {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db\SQLite3;
|
||||
namespace JKingWeb\Arsse\Db\SQLite3;
|
||||
|
||||
class Result implements \JKingWeb\NewsSync\Db\Result {
|
||||
class Result implements \JKingWeb\Arsse\Db\Result {
|
||||
protected $st;
|
||||
protected $set;
|
||||
protected $pos = 0;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db\SQLite3;
|
||||
use JKingWeb\NewsSync\Db\Exception;
|
||||
use JKingWeb\NewsSync\Db\ExceptionInput;
|
||||
use JKingWeb\NewsSync\Db\ExceptionTimeout;
|
||||
namespace JKingWeb\Arsse\Db\SQLite3;
|
||||
use JKingWeb\Arsse\Db\Exception;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Db\ExceptionTimeout;
|
||||
|
||||
class Statement extends \JKingWeb\NewsSync\Db\AbstractStatement {
|
||||
class Statement extends \JKingWeb\Arsse\Db\AbstractStatement {
|
||||
use ExceptionBuilder;
|
||||
|
||||
const SQLITE_BUSY = 5;
|
||||
|
@ -46,7 +46,7 @@ class Statement extends \JKingWeb\NewsSync\Db\AbstractStatement {
|
|||
])[$part];
|
||||
}
|
||||
|
||||
public function runArray(array $values = null): \JKingWeb\NewsSync\Db\Result {
|
||||
public function runArray(array $values = null): \JKingWeb\Arsse\Db\Result {
|
||||
$this->st->clear();
|
||||
$l = sizeof($values);
|
||||
for($a = 0; $a < $l; $a++) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Db;
|
||||
namespace JKingWeb\Arsse\Db;
|
||||
|
||||
interface Statement {
|
||||
const TS_TIME = -1;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
class Exception extends AbstractException {
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
class ExceptionFatal extends AbstractException {
|
||||
public function __construct($msg = "", $code = 0, $e = null) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
use PicoFeed\Reader\Reader;
|
||||
use PicoFeed\PicoFeedException;
|
||||
use PicoFeed\Reader\Favicon;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Feed;
|
||||
namespace JKingWeb\Arsse\Feed;
|
||||
|
||||
class Exception extends \JKingWeb\NewsSync\AbstractException {
|
||||
class Exception extends \JKingWeb\Arsse\AbstractException {
|
||||
public function __construct($url, \Throwable $e) {
|
||||
$className = get_class($e);
|
||||
// Convert the exception thrown by PicoFeed to the one to be thrown here.
|
||||
|
|
18
lib/Lang.php
18
lib/Lang.php
|
@ -1,19 +1,19 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
use \Webmozart\Glob\Glob;
|
||||
|
||||
class Lang {
|
||||
const DEFAULT = "en"; // fallback locale
|
||||
const REQUIRED = [ // collection of absolutely required strings to handle pathological errors
|
||||
'Exception.JKingWeb/NewsSync/Exception.uncoded' => 'The specified exception symbol {0} has no code specified in AbstractException.php',
|
||||
'Exception.JKingWeb/NewsSync/Exception.unknown' => 'An unknown error has occurred',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.defaultFileMissing' => 'Default language file "{0}" missing',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.fileMissing' => 'Language file "{0}" is not available',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.fileUnreadable' => 'Insufficient permissions to read language file "{0}"',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.fileCorrupt' => 'Language file "{0}" is corrupt or does not conform to expected format',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.stringMissing' => 'Message string "{msgID}" missing from all loaded language files ({fileList})',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.stringInvalid' => 'Message string "{msgID}" is not a valid ICU message string (language files loaded: {fileList})',
|
||||
'Exception.JKingWeb/Arsse/Exception.uncoded' => 'The specified exception symbol {0} has no code specified in AbstractException.php',
|
||||
'Exception.JKingWeb/Arsse/Exception.unknown' => 'An unknown error has occurred',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.defaultFileMissing' => 'Default language file "{0}" missing',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.fileMissing' => 'Language file "{0}" is not available',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.fileUnreadable' => 'Insufficient permissions to read language file "{0}"',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.fileCorrupt' => 'Language file "{0}" is corrupt or does not conform to expected format',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.stringMissing' => 'Message string "{msgID}" missing from all loaded language files ({fileList})',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.stringInvalid' => 'Message string "{msgID}" is not a valid ICU message string (language files loaded: {fileList})',
|
||||
];
|
||||
|
||||
static public $path = BASE."locale".DIRECTORY_SEPARATOR; // path to locale files; this is a public property to facilitate unit testing
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Lang;
|
||||
namespace JKingWeb\Arsse\Lang;
|
||||
|
||||
class Exception extends \JKingWeb\NewsSync\AbstractException {
|
||||
class Exception extends \JKingWeb\Arsse\AbstractException {
|
||||
static $test = false; // used during PHPUnit testing only
|
||||
|
||||
function __construct(string $msgID = "", $vars = null, \Throwable $e = null) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
class REST {
|
||||
protected $apis = [
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\REST;
|
||||
namespace JKingWeb\Arsse\REST;
|
||||
|
||||
abstract class AbstractHandler implements Handler {
|
||||
abstract function __construct(\JKingWeb\NewsSync\RuntimeData $data);
|
||||
abstract function __construct(\JKingWeb\Arsse\RuntimeData $data);
|
||||
abstract function dispatch(Request $req): Response;
|
||||
|
||||
protected function parseURL(string $url): array {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\REST;
|
||||
namespace JKingWeb\Arsse\REST;
|
||||
|
||||
interface Handler {
|
||||
function __construct(\JKingWeb\NewsSync\RuntimeData $data);
|
||||
function __construct(\JKingWeb\Arsse\RuntimeData $data);
|
||||
function dispatch(Request $req): Response;
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\REST\NextCloudNews;
|
||||
use JKingWeb\NewsSync\REST\Response;
|
||||
namespace JKingWeb\Arsse\REST\NextCloudNews;
|
||||
use JKingWeb\Arsse\REST\Response;
|
||||
|
||||
class Versions extends \JKingWeb\NewsSync\REST\AbstractHandler {
|
||||
function __construct(\JKingWeb\NewsSync\RuntimeData $data) {
|
||||
class Versions extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
function __construct(\JKingWeb\Arsse\RuntimeData $data) {
|
||||
// runtime data is not needed; this method is deliberately empty
|
||||
}
|
||||
|
||||
function dispatch(\JKingWeb\NewsSync\REST\Request $req): \JKingWeb\NewsSync\REST\Response {
|
||||
function dispatch(\JKingWeb\Arsse\REST\Request $req): \JKingWeb\Arsse\REST\Response {
|
||||
// parse the URL and populate $path and $query
|
||||
extract($this->parseURL($req->url));
|
||||
// if a method other than GET was used, this is an error
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\REST;
|
||||
namespace JKingWeb\Arsse\REST;
|
||||
|
||||
class Request {
|
||||
public $method = "GET";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\REST;
|
||||
namespace JKingWeb\Arsse\REST;
|
||||
|
||||
class Response {
|
||||
const T_JSON = "application/json";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
class RuntimeData {
|
||||
public $conf;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
class User {
|
||||
public $id = null;
|
||||
|
@ -23,7 +23,7 @@ class User {
|
|||
return $classes;
|
||||
}
|
||||
|
||||
public function __construct(\JKingWeb\NewsSync\RuntimeData $data) {
|
||||
public function __construct(\JKingWeb\Arsse\RuntimeData $data) {
|
||||
$this->data = $data;
|
||||
$driver = $data->conf->userDriver;
|
||||
$this->u = new $driver($data);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\User;
|
||||
namespace JKingWeb\Arsse\User;
|
||||
|
||||
Interface Driver {
|
||||
const FUNC_NOT_IMPLEMENTED = 0;
|
||||
|
@ -14,7 +14,7 @@ Interface Driver {
|
|||
const RIGHTS_GLOBAL_ADMIN = 100; // is completely unrestricted
|
||||
|
||||
// returns an instance of a class implementing this interface. Implemented as a static method for consistency with database classes
|
||||
function __construct(\JKingWeb\NewsSync\RuntimeData $data);
|
||||
function __construct(\JKingWeb\Arsse\RuntimeData $data);
|
||||
// returns a human-friendly name for the driver (for display in installer, for example)
|
||||
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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\User;
|
||||
namespace JKingWeb\Arsse\User;
|
||||
|
||||
class Exception extends \JKingWeb\NewsSync\AbstractException {
|
||||
class Exception extends \JKingWeb\Arsse\AbstractException {
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\User;
|
||||
namespace JKingWeb\Arsse\User;
|
||||
|
||||
class ExceptionAuthz extends Exception {
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\User;
|
||||
namespace JKingWeb\Arsse\User;
|
||||
|
||||
class ExceptionNotImplemented extends Exception {
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\User\Internal;
|
||||
use JKingWeb\NewsSync\Lang;
|
||||
use JKingWeb\NewsSync\User\Driver as Iface;
|
||||
namespace JKingWeb\Arsse\User\Internal;
|
||||
use JKingWeb\Arsse\Lang;
|
||||
use JKingWeb\Arsse\User\Driver as Iface;
|
||||
|
||||
final class Driver implements Iface {
|
||||
use InternalFunctions;
|
||||
|
@ -22,7 +22,7 @@ final class Driver implements Iface {
|
|||
"userRightsSet" => Iface::FUNC_INTERNAL,
|
||||
];
|
||||
|
||||
static public function create(\JKingWeb\NewsSync\RuntimeData $data): Driver {
|
||||
static public function create(\JKingWeb\Arsse\RuntimeData $data): Driver {
|
||||
return new static($data);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\User\Internal;
|
||||
namespace JKingWeb\Arsse\User\Internal;
|
||||
|
||||
trait InternalFunctions {
|
||||
protected $actor = [];
|
||||
|
||||
public function __construct(\JKingWeb\NewsSync\RuntimeData $data) {
|
||||
public function __construct(\JKingWeb\Arsse\RuntimeData $data) {
|
||||
$this->data = $data;
|
||||
$this->db = $this->data->db;
|
||||
}
|
||||
|
|
112
locale/en.php
112
locale/en.php
|
@ -5,64 +5,64 @@ return [
|
|||
'Driver.Db.SQLite3.Name' => 'SQLite 3',
|
||||
|
||||
// this should only be encountered in testing (because tests should cover all exceptions!)
|
||||
'Exception.JKingWeb/NewsSync/Exception.uncoded' => 'The specified exception symbol {0} has no code specified in AbstractException.php',
|
||||
'Exception.JKingWeb/Arsse/Exception.uncoded' => 'The specified exception symbol {0} has no code specified in AbstractException.php',
|
||||
// this should not usually be encountered
|
||||
'Exception.JKingWeb/NewsSync/Exception.unknown' => 'An unknown error has occurred',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.defaultFileMissing' => 'Default language file "{0}" missing',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.fileMissing' => 'Language file "{0}" is not available',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.fileUnreadable' => 'Insufficient permissions to read language file "{0}"',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.fileCorrupt' => 'Language file "{0}" is corrupt or does not conform to expected format',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.stringMissing' => 'Message string "{msgID}" missing from all loaded language files ({fileList})',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.stringInvalid' => 'Message string "{msgID}" is not a valid ICU message string (language files loaded: {fileList})',
|
||||
'Exception.JKingWeb/NewsSync/Conf/Exception.fileMissing' => 'Configuration file "{0}" does not exist',
|
||||
'Exception.JKingWeb/NewsSync/Conf/Exception.fileUnreadable' => 'Insufficient permissions to read configuration file "{0}"',
|
||||
'Exception.JKingWeb/NewsSync/Conf/Exception.fileUncreatable' => 'Insufficient permissions to write new configuration file "{0}"',
|
||||
'Exception.JKingWeb/NewsSync/Conf/Exception.fileUnwritable' => 'Insufficient permissions to overwrite configuration file "{0}"',
|
||||
'Exception.JKingWeb/NewsSync/Conf/Exception.fileCorrupt' => 'Configuration file "{0}" is corrupt or does not conform to expected format',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.extMissing' => 'Required PHP extension for driver "{0}" not installed',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.fileMissing' => 'Database file "{0}" does not exist',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.fileUnreadable' => 'Insufficient permissions to open database file "{0}" for reading',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.fileUnwritable' => 'Insufficient permissions to open database file "{0}" for writing',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.fileUnusable' => 'Insufficient permissions to open database file "{0}" for reading or writing',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.fileUncreatable' => 'Insufficient permissions to create new database file "{0}"',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.fileCorrupt' => 'Database file "{0}" is corrupt or not a valid database',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.paramTypeInvalid' => 'Prepared statement parameter type "{0}" is invalid',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.paramTypeUnknown' => 'Prepared statement parameter type "{0}" is valid, but not implemented',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.paramTypeMissing' => 'Prepared statement parameter type for parameter #{0} was not specified',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.updateManual' =>
|
||||
'Exception.JKingWeb/Arsse/Exception.unknown' => 'An unknown error has occurred',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.defaultFileMissing' => 'Default language file "{0}" missing',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.fileMissing' => 'Language file "{0}" is not available',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.fileUnreadable' => 'Insufficient permissions to read language file "{0}"',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.fileCorrupt' => 'Language file "{0}" is corrupt or does not conform to expected format',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.stringMissing' => 'Message string "{msgID}" missing from all loaded language files ({fileList})',
|
||||
'Exception.JKingWeb/Arsse/Lang/Exception.stringInvalid' => 'Message string "{msgID}" is not a valid ICU message string (language files loaded: {fileList})',
|
||||
'Exception.JKingWeb/Arsse/Conf/Exception.fileMissing' => 'Configuration file "{0}" does not exist',
|
||||
'Exception.JKingWeb/Arsse/Conf/Exception.fileUnreadable' => 'Insufficient permissions to read configuration file "{0}"',
|
||||
'Exception.JKingWeb/Arsse/Conf/Exception.fileUncreatable' => 'Insufficient permissions to write new configuration file "{0}"',
|
||||
'Exception.JKingWeb/Arsse/Conf/Exception.fileUnwritable' => 'Insufficient permissions to overwrite configuration file "{0}"',
|
||||
'Exception.JKingWeb/Arsse/Conf/Exception.fileCorrupt' => 'Configuration file "{0}" is corrupt or does not conform to expected format',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.extMissing' => 'Required PHP extension for driver "{0}" not installed',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.fileMissing' => 'Database file "{0}" does not exist',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.fileUnreadable' => 'Insufficient permissions to open database file "{0}" for reading',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.fileUnwritable' => 'Insufficient permissions to open database file "{0}" for writing',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.fileUnusable' => 'Insufficient permissions to open database file "{0}" for reading or writing',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.fileUncreatable' => 'Insufficient permissions to create new database file "{0}"',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.fileCorrupt' => 'Database file "{0}" is corrupt or not a valid database',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.paramTypeInvalid' => 'Prepared statement parameter type "{0}" is invalid',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.paramTypeUnknown' => 'Prepared statement parameter type "{0}" is valid, but not implemented',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.paramTypeMissing' => 'Prepared statement parameter type for parameter #{0} was not specified',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.updateManual' =>
|
||||
'{from_version, select,
|
||||
0 {{driver_name} database is configured for manual updates and is not initialized; please populate the database with the base schema}
|
||||
other {{driver_name} database is configured for manual updates; please update from schema version {current} to version {target}}
|
||||
}',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.updateManualOnly' =>
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.updateManualOnly' =>
|
||||
'{from_version, select,
|
||||
0 {{driver_name} database must be updated manually and is not initialized; please populate the database with the base schema}
|
||||
other {{driver_name} database must be updated manually; please update from schema version {current} to version {target}}
|
||||
}',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.updateFileMissing' => 'Automatic updating of the {driver_name} database failed due to instructions for updating from version {current} not being available',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.updateFileUnreadable' => 'Automatic updating of the {driver_name} database failed due to insufficient permissions to read instructions for updating from version {current}',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.updateFileUnusable' => 'Automatic updating of the {driver_name} database failed due to an error reading instructions for updating from version {current}',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.updateFileError' => 'Automatic updating of the {driver_name} database failed updating from version {current} with the following error: "{message}"',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.updateFileIncomplete' => 'Automatic updating of the {driver_name} database failed due to instructions for updating from version {current} being incomplete',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.updateTooNew' =>
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.updateFileMissing' => 'Automatic updating of the {driver_name} database failed due to instructions for updating from version {current} not being available',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.updateFileUnreadable' => 'Automatic updating of the {driver_name} database failed due to insufficient permissions to read instructions for updating from version {current}',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.updateFileUnusable' => 'Automatic updating of the {driver_name} database failed due to an error reading instructions for updating from version {current}',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.updateFileError' => 'Automatic updating of the {driver_name} database failed updating from version {current} with the following error: "{message}"',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.updateFileIncomplete' => 'Automatic updating of the {driver_name} database failed due to instructions for updating from version {current} being incomplete',
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.updateTooNew' =>
|
||||
'{difference, select,
|
||||
0 {Automatic updating of the {driver_name} database failed because it is already up to date with the requested version, {target}}
|
||||
other {Automatic updating of the {driver_name} database failed because its version, {current}, is newer than the requested version, {target}}
|
||||
}',
|
||||
'Exception.JKingWeb/NewsSync/Db/Exception.engineErrorGeneral' => '{0}',
|
||||
'Exception.JKingWeb/NewsSync/Db/ExceptionInput.missing' => 'Required field "{field}" missing while performing action "{action}"',
|
||||
'Exception.JKingWeb/NewsSync/Db/ExceptionInput.whitespace' => 'Required field "{field}" of action "{action}" may not contain only whitespace',
|
||||
'Exception.JKingWeb/NewsSync/Db/ExceptionInput.tooLong' => 'Required field "{field}" of action "{action}" has a maximum length of {max}',
|
||||
'Exception.JKingWeb/NewsSync/Db/ExceptionInput.tooShort' => 'Required field "{field}" of action "{action}" has a minimum length of {min}',
|
||||
'Exception.JKingWeb/NewsSync/Db/ExceptionInput.idMissing' => 'Referenced ID ({id}) in field "{field}" does not exist',
|
||||
'Exception.JKingWeb/NewsSync/Db/ExceptionInput.constraintViolation' => '{0}',
|
||||
'Exception.JKingWeb/NewsSync/Db/ExceptionInput.typeViolation' => '{0}',
|
||||
'Exception.JKingWeb/NewsSync/Db/ExceptionTimeout.general' => '{0}',
|
||||
'Exception.JKingWeb/NewsSync/User/Exception.alreadyExists' => 'Could not perform action "{action}" because the user {user} already exists',
|
||||
'Exception.JKingWeb/NewsSync/User/Exception.doesNotExist' => 'Could not perform action "{action}" because the user {user} does not exist',
|
||||
'Exception.JKingWeb/NewsSync/User/Exception.authMissing' => 'Please log in to proceed',
|
||||
'Exception.JKingWeb/NewsSync/User/Exception.authFailed' => 'Authentication failed',
|
||||
'Exception.JKingWeb/NewsSync/User/ExceptionAuthz.notAuthorized' =>
|
||||
'Exception.JKingWeb/Arsse/Db/Exception.engineErrorGeneral' => '{0}',
|
||||
'Exception.JKingWeb/Arsse/Db/ExceptionInput.missing' => 'Required field "{field}" missing while performing action "{action}"',
|
||||
'Exception.JKingWeb/Arsse/Db/ExceptionInput.whitespace' => 'Required field "{field}" of action "{action}" may not contain only whitespace',
|
||||
'Exception.JKingWeb/Arsse/Db/ExceptionInput.tooLong' => 'Required field "{field}" of action "{action}" has a maximum length of {max}',
|
||||
'Exception.JKingWeb/Arsse/Db/ExceptionInput.tooShort' => 'Required field "{field}" of action "{action}" has a minimum length of {min}',
|
||||
'Exception.JKingWeb/Arsse/Db/ExceptionInput.idMissing' => 'Referenced ID ({id}) in field "{field}" does not exist',
|
||||
'Exception.JKingWeb/Arsse/Db/ExceptionInput.constraintViolation' => '{0}',
|
||||
'Exception.JKingWeb/Arsse/Db/ExceptionInput.typeViolation' => '{0}',
|
||||
'Exception.JKingWeb/Arsse/Db/ExceptionTimeout.general' => '{0}',
|
||||
'Exception.JKingWeb/Arsse/User/Exception.alreadyExists' => 'Could not perform action "{action}" because the user {user} already exists',
|
||||
'Exception.JKingWeb/Arsse/User/Exception.doesNotExist' => 'Could not perform action "{action}" because the user {user} does not exist',
|
||||
'Exception.JKingWeb/Arsse/User/Exception.authMissing' => 'Please log in to proceed',
|
||||
'Exception.JKingWeb/Arsse/User/Exception.authFailed' => 'Authentication failed',
|
||||
'Exception.JKingWeb/Arsse/User/ExceptionAuthz.notAuthorized' =>
|
||||
'{action, select,
|
||||
userList {{user, select,
|
||||
global {Authenticated user is not authorized to view the global user list}
|
||||
|
@ -70,15 +70,15 @@ return [
|
|||
}}
|
||||
other {Authenticated user is not authorized to perform the action "{action}" on behalf of {user}}
|
||||
}',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.invalidCertificate' => 'Could not download feed "{url}" because its server is serving an invalid SSL certificate',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.invalidURL' => 'Feed URL "{url}" is invalid',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.maxRedirect' => 'Could not download feed "{url}" because its server reached its maximum number of HTTP redirections',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.maxSize' => 'Could not download feed "{url}" because its size exceeds the maximum allowed on its server',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.timeout' => 'Could not download feed "{url}" because its server timed out',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.forbidden' => 'Could not download feed "{url}" because you do not have permission to access it',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.unauthorized' => 'Could not download feed "{url}" because you provided insufficient or invalid credentials',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.malformed' => 'Could not parse feed "{url}" because it is malformed',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.xmlEntity' => 'Refused to parse feed "{url}" because it contains an XXE attack',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.subscriptionNotFound' => 'Unable to find a feed at location "{url}"',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.unsupportedFormat' => 'Feed "{url}" is of an unsupported format'
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.invalidCertificate' => 'Could not download feed "{url}" because its server is serving an invalid SSL certificate',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.invalidURL' => 'Feed URL "{url}" is invalid',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.maxRedirect' => 'Could not download feed "{url}" because its server reached its maximum number of HTTP redirections',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.maxSize' => 'Could not download feed "{url}" because its size exceeds the maximum allowed on its server',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.timeout' => 'Could not download feed "{url}" because its server timed out',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.forbidden' => 'Could not download feed "{url}" because you do not have permission to access it',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.unauthorized' => 'Could not download feed "{url}" because you provided insufficient or invalid credentials',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.malformed' => 'Could not parse feed "{url}" because it is malformed',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.xmlEntity' => 'Refused to parse feed "{url}" because it contains an XXE attack',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.subscriptionNotFound' => 'Unable to find a feed at location "{url}"',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.unsupportedFormat' => 'Feed "{url}" is of an unsupported format'
|
||||
];
|
|
@ -1,5 +1,5 @@
|
|||
-- settings
|
||||
create table newssync_settings(
|
||||
create table arsse_settings(
|
||||
key varchar(255) primary key not null, -- setting key
|
||||
value varchar(255), -- setting value, serialized as a string
|
||||
type varchar(255) not null check(
|
||||
|
@ -8,7 +8,7 @@ create table newssync_settings(
|
|||
) without rowid;
|
||||
|
||||
-- users
|
||||
create table newssync_users(
|
||||
create table arsse_users(
|
||||
id TEXT primary key not null, -- user id
|
||||
password TEXT, -- password, salted and hashed; if using external authentication this would be blank
|
||||
name TEXT, -- display name
|
||||
|
@ -19,7 +19,7 @@ create table newssync_users(
|
|||
) without rowid;
|
||||
|
||||
-- newsfeeds, deduplicated
|
||||
create table newssync_feeds(
|
||||
create table arsse_feeds(
|
||||
id integer primary key not null, -- sequence number
|
||||
url TEXT not null, -- URL of feed
|
||||
title TEXT, -- default title of feed
|
||||
|
@ -36,23 +36,23 @@ create table newssync_feeds(
|
|||
);
|
||||
|
||||
-- users' subscriptions to newsfeeds, with settings
|
||||
create table newssync_subscriptions(
|
||||
create table arsse_subscriptions(
|
||||
id integer primary key not null, -- sequence number
|
||||
owner TEXT not null references newssync_users(id) on delete cascade on update cascade, -- owner of subscription
|
||||
feed integer not null references newssync_feeds(id) on delete cascade, -- feed for the subscription
|
||||
owner TEXT not null references arsse_users(id) on delete cascade on update cascade, -- owner of subscription
|
||||
feed integer not null references arsse_feeds(id) on delete cascade, -- feed for the subscription
|
||||
added datetime not null default CURRENT_TIMESTAMP, -- time at which feed was added
|
||||
modified datetime not null default CURRENT_TIMESTAMP, -- date at which subscription properties were last modified
|
||||
title TEXT, -- user-supplied title
|
||||
order_type int not null default 0, -- NextCloud sort order
|
||||
pinned boolean not null default 0, -- whether feed is pinned (always sorts at top)
|
||||
folder integer references newssync_folders(id) on delete cascade, -- TT-RSS category (nestable); the first-level category (which acts as NextCloud folder) is joined in when needed
|
||||
folder integer references arsse_folders(id) on delete cascade, -- TT-RSS category (nestable); the first-level category (which acts as NextCloud folder) is joined in when needed
|
||||
unique(owner,feed) -- a given feed should only appear once for a given owner
|
||||
);
|
||||
|
||||
-- TT-RSS categories and NextCloud folders
|
||||
create table newssync_folders(
|
||||
create table arsse_folders(
|
||||
id integer primary key not null, -- sequence number
|
||||
owner TEXT not null references newssync_users(id) on delete cascade on update cascade, -- owner of folder
|
||||
owner TEXT not null references arsse_users(id) on delete cascade on update cascade, -- owner of folder
|
||||
parent integer default null, -- parent folder id
|
||||
root integer default null, -- first-level folder (NextCloud folder)
|
||||
name TEXT not null, -- folder name
|
||||
|
@ -61,9 +61,9 @@ create table newssync_folders(
|
|||
);
|
||||
|
||||
-- entries in newsfeeds
|
||||
create table newssync_articles(
|
||||
create table arsse_articles(
|
||||
id integer primary key not null, -- sequence number
|
||||
feed integer not null references newssync_feeds(id) on delete cascade, -- feed for the subscription
|
||||
feed integer not null references arsse_feeds(id) on delete cascade, -- feed for the subscription
|
||||
url TEXT not null, -- URL of article
|
||||
title TEXT, -- article title
|
||||
author TEXT, -- author's name
|
||||
|
@ -78,35 +78,35 @@ create table newssync_articles(
|
|||
);
|
||||
|
||||
-- enclosures associated with articles
|
||||
create table newssync_enclosures(
|
||||
article integer not null references newssync_articles(id) on delete cascade,
|
||||
create table arsse_enclosures(
|
||||
article integer not null references arsse_articles(id) on delete cascade,
|
||||
url TEXT,
|
||||
type varchar(255)
|
||||
);
|
||||
|
||||
-- users' actions on newsfeed entries
|
||||
create table newssync_subscription_articles(
|
||||
create table arsse_subscription_articles(
|
||||
id integer primary key not null,
|
||||
article integer not null references newssync_articles(id) on delete cascade,
|
||||
article integer not null references arsse_articles(id) on delete cascade,
|
||||
read boolean not null default 0,
|
||||
starred boolean not null default 0,
|
||||
modified datetime not null default CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- user labels associated with newsfeed entries
|
||||
create table newssync_labels(
|
||||
sub_article integer not null references newssync_subscription_articles(id) on delete cascade, --
|
||||
owner TEXT not null references newssync_users(id) on delete cascade on update cascade,
|
||||
create table arsse_labels(
|
||||
sub_article integer not null references arsse_subscription_articles(id) on delete cascade, --
|
||||
owner TEXT not null references arsse_users(id) on delete cascade on update cascade,
|
||||
name TEXT
|
||||
);
|
||||
create index newssync_label_names on newssync_labels(name);
|
||||
create index arsse_label_names on arsse_labels(name);
|
||||
|
||||
-- author labels ("categories" in RSS/Atom parlance) associated with newsfeed entries
|
||||
create table newssync_tags(
|
||||
article integer not null references newssync_articles(id) on delete cascade,
|
||||
create table arsse_tags(
|
||||
article integer not null references arsse_articles(id) on delete cascade,
|
||||
name TEXT
|
||||
);
|
||||
|
||||
-- set version marker
|
||||
pragma user_version = 1;
|
||||
insert into newssync_settings values('schema_version',1,'int');
|
||||
insert into arsse_settings values('schema_version',1,'int');
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
use \org\bovigo\vfs\vfsStream;
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
|
||||
class TestDbDriverSQLite3 extends \PHPUnit\Framework\TestCase {
|
||||
|
@ -267,7 +267,7 @@ class TestDbDriverSQLite3 extends \PHPUnit\Framework\TestCase {
|
|||
$this->assertFalse($this->drv->isLocked());
|
||||
$this->assertTrue($this->drv->lock());
|
||||
$this->assertFalse($this->drv->isLocked());
|
||||
$this->drv->exec("CREATE TABLE newssync_settings(key primary key, value, type) without rowid; PRAGMA user_version=1");
|
||||
$this->drv->exec("CREATE TABLE arsse_settings(key primary key, value, type) without rowid; PRAGMA user_version=1");
|
||||
$this->assertTrue($this->drv->lock());
|
||||
$this->assertTrue($this->drv->isLocked());
|
||||
$this->assertFalse($this->drv->lock());
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
|
||||
class TestDbResultSQLite3 extends \PHPUnit\Framework\TestCase {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
use JKingWeb\NewsSync\Db\Statement;
|
||||
namespace JKingWeb\Arsse;
|
||||
use JKingWeb\Arsse\Db\Statement;
|
||||
|
||||
|
||||
class TestDbStatementSQLite3 extends \PHPUnit\Framework\TestCase {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
use \org\bovigo\vfs\vfsStream;
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@ class TestDbUpdateSQLite3 extends \PHPUnit\Framework\TestCase {
|
|||
protected $vfs;
|
||||
protected $base;
|
||||
|
||||
const MINIMAL1 = "create table newssync_settings(key text primary key not null, value text, type text not null); pragma user_version=1";
|
||||
const MINIMAL1 = "create table arsse_settings(key text primary key not null, value text, type text not null); pragma user_version=1";
|
||||
const MINIMAL2 = "pragma user_version=2";
|
||||
|
||||
function setUp() {
|
||||
|
@ -51,7 +51,7 @@ class TestDbUpdateSQLite3 extends \PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
function testLoadIncompleteFile() {
|
||||
file_put_contents($this->base."0.sql", "create table newssync_settings(key text primary key not null, value text, type text not null);");
|
||||
file_put_contents($this->base."0.sql", "create table arsse_settings(key text primary key not null, value text, type text not null);");
|
||||
$this->assertException("updateFileIncomplete", "Db");
|
||||
$this->drv->schemaUpdate(1);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
|
||||
class TestDatabase extends \PHPUnit\Framework\TestCase {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
|
||||
class TestException extends \PHPUnit\Framework\TestCase {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
use \org\bovigo\vfs\vfsStream;
|
||||
|
||||
|
||||
|
@ -43,7 +43,7 @@ class TestLang extends \PHPUnit\Framework\TestCase {
|
|||
function testLoadDefaultLanguage() {
|
||||
$this->assertEquals(Lang::DEFAULT, Lang::set(Lang::DEFAULT, true));
|
||||
$str = Lang::dump();
|
||||
$this->assertArrayHasKey('Exception.JKingWeb/NewsSync/Exception.uncoded', $str);
|
||||
$this->assertArrayHasKey('Exception.JKingWeb/Arsse/Exception.uncoded', $str);
|
||||
$this->assertArrayHasKey('Test.presentText', $str);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ class TestLang extends \PHPUnit\Framework\TestCase {
|
|||
Lang::set(Lang::DEFAULT, true);
|
||||
$this->assertEquals("ja", Lang::set("ja", true));
|
||||
$str = Lang::dump();
|
||||
$this->assertArrayHasKey('Exception.JKingWeb/NewsSync/Exception.uncoded', $str);
|
||||
$this->assertArrayHasKey('Exception.JKingWeb/Arsse/Exception.uncoded', $str);
|
||||
$this->assertArrayHasKey('Test.presentText', $str);
|
||||
$this->assertArrayHasKey('Test.absentText', $str);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
use \org\bovigo\vfs\vfsStream;
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
use \org\bovigo\vfs\vfsStream;
|
||||
|
||||
|
||||
|
@ -64,7 +64,7 @@ class TestLangComplex extends \PHPUnit\Framework\TestCase {
|
|||
*/
|
||||
function testFetchAMessageWithSingleNumericParameter() {
|
||||
Lang::set("en_ca", true);
|
||||
$this->assertEquals('Default language file "en" missing', Lang::msg('Exception.JKingWeb/NewsSync/Lang/Exception.defaultFileMissing', Lang::DEFAULT));
|
||||
$this->assertEquals('Default language file "en" missing', Lang::msg('Exception.JKingWeb/Arsse/Lang/Exception.defaultFileMissing', Lang::DEFAULT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,7 +79,7 @@ class TestLangComplex extends \PHPUnit\Framework\TestCase {
|
|||
* @depends testFetchAMessage
|
||||
*/
|
||||
function testFetchAMessageWithNamedParameters() {
|
||||
$this->assertEquals('Message string "Test.absentText" missing from all loaded language files (en)', Lang::msg('Exception.JKingWeb/NewsSync/Lang/Exception.stringMissing', ['msgID' => 'Test.absentText', 'fileList' => 'en']));
|
||||
$this->assertEquals('Message string "Test.absentText" missing from all loaded language files (en)', Lang::msg('Exception.JKingWeb/Arsse/Lang/Exception.stringMissing', ['msgID' => 'Test.absentText', 'fileList' => 'en']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
use JKingWeb\NewsSync\Rest\Request;
|
||||
use JKingWeb\NewsSync\Rest\Response;
|
||||
namespace JKingWeb\Arsse;
|
||||
use JKingWeb\Arsse\Rest\Request;
|
||||
use JKingWeb\Arsse\Rest\Response;
|
||||
|
||||
|
||||
class TestNCNVersionDiscovery extends \PHPUnit\Framework\TestCase {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
|
||||
class TestAuthorization extends \PHPUnit\Framework\TestCase {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
|
||||
class TestUserInternalDriver extends \PHPUnit\Framework\TestCase {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
|
||||
class TestUserMockExternal extends \PHPUnit\Framework\TestCase {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
|
||||
class TestUserMockInternal extends \PHPUnit\Framework\TestCase {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test\Db;
|
||||
use JKingWeb\NewsSync\Db\Statement;
|
||||
namespace JKingWeb\Arsse\Test\Db;
|
||||
use JKingWeb\Arsse\Db\Statement;
|
||||
|
||||
trait BindingTests {
|
||||
function testBindNull() {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test\Db;
|
||||
namespace JKingWeb\Arsse\Test\Db;
|
||||
|
||||
trait Tools {
|
||||
function prime(\JKingWeb\NewsSync\Db\Driver $drv, array $data): bool {
|
||||
function prime(\JKingWeb\Arsse\Db\Driver $drv, array $data): bool {
|
||||
$drv->begin();
|
||||
foreach($data as $table => $info) {
|
||||
$cols = implode(",", array_keys($info['columns']));
|
||||
|
@ -18,7 +18,7 @@ trait Tools {
|
|||
return true;
|
||||
}
|
||||
|
||||
function compare(\JKingWeb\NewsSync\Db\Driver $drv, array $expected): bool {
|
||||
function compare(\JKingWeb\Arsse\Db\Driver $drv, array $expected): bool {
|
||||
foreach($expected as $table => $info) {
|
||||
$cols = implode(",", array_keys($info['columns']));
|
||||
foreach($drv->prepare("SELECT $cols from $table")->run() as $num => $row) {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test\Lang;
|
||||
use \org\bovigo\vfs\vfsStream, \JKingWeb\NewsSync\Lang;
|
||||
namespace JKingWeb\Arsse\Test\Lang;
|
||||
use \org\bovigo\vfs\vfsStream, \JKingWeb\Arsse\Lang;
|
||||
|
||||
|
||||
|
||||
trait Setup {
|
||||
static function setUpBeforeClass() {
|
||||
// this is required to keep from having exceptions in Lang::msg() in turn calling Lang::msg() and looping
|
||||
\JKingWeb\NewsSync\Lang\Exception::$test = true;
|
||||
\JKingWeb\Arsse\Lang\Exception::$test = true;
|
||||
// test files
|
||||
self::$files = [
|
||||
'en.php' => '<?php return ["Test.presentText" => "and the Philosopher\'s Stone"];',
|
||||
|
@ -38,7 +38,7 @@ trait Setup {
|
|||
}
|
||||
|
||||
static function tearDownAfterClass() {
|
||||
\JKingWeb\NewsSync\Lang\Exception::$test = false;
|
||||
\JKingWeb\Arsse\Lang\Exception::$test = false;
|
||||
Lang::$path = self::$defaultPath;
|
||||
self::$path = null;
|
||||
self::$vfs = null;
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test;
|
||||
namespace JKingWeb\Arsse\Test;
|
||||
|
||||
class RuntimeData extends \JKingWeb\NewsSync\RuntimeData {
|
||||
class RuntimeData extends \JKingWeb\Arsse\RuntimeData {
|
||||
public $conf;
|
||||
public $db;
|
||||
public $user;
|
||||
|
||||
public function __construct(\JKingWeb\NewsSync\Conf $conf = null) {
|
||||
public function __construct(\JKingWeb\Arsse\Conf $conf = null) {
|
||||
$this->conf = $conf;
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test;
|
||||
use \JKingWeb\NewsSync\Exception;
|
||||
namespace JKingWeb\Arsse\Test;
|
||||
use \JKingWeb\Arsse\Exception;
|
||||
|
||||
trait Tools {
|
||||
function assertException(string $msg, string $prefix = "", string $type = "Exception") {
|
||||
$class = \JKingWeb\NewsSync\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type;
|
||||
$class = \JKingWeb\Arsse\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type;
|
||||
$msgID = ($prefix !== "" ? $prefix . "/" : "") . $type. ".$msg";
|
||||
if(array_key_exists($msgID, Exception::CODES)) {
|
||||
$code = Exception::CODES[$msgID];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test\User;
|
||||
use JKingWeb\NewsSync\User\Driver;
|
||||
namespace JKingWeb\Arsse\Test\User;
|
||||
use JKingWeb\Arsse\User\Driver;
|
||||
|
||||
trait CommonTests {
|
||||
function testListUsers() {
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test\User;
|
||||
use JKingWeb\NewsSync\User\Driver;
|
||||
use JKingWeb\NewsSync\User\Exception;
|
||||
use JKingWeb\NewsSync\User\ExceptionAuthz;
|
||||
namespace JKingWeb\Arsse\Test\User;
|
||||
use JKingWeb\Arsse\User\Driver;
|
||||
use JKingWeb\Arsse\User\Exception;
|
||||
use JKingWeb\Arsse\User\ExceptionAuthz;
|
||||
use PasswordGenerator\Generator as PassGen;
|
||||
|
||||
class Database extends DriverSkeleton {
|
||||
|
||||
public $db = [];
|
||||
|
||||
public function __construct(\JKingWeb\NewsSync\RuntimeData $data) {
|
||||
public function __construct(\JKingWeb\Arsse\RuntimeData $data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test\User;
|
||||
use JKingWeb\NewsSync\User\Driver;
|
||||
use JKingWeb\NewsSync\User\Exception;
|
||||
namespace JKingWeb\Arsse\Test\User;
|
||||
use JKingWeb\Arsse\User\Driver;
|
||||
use JKingWeb\Arsse\User\Exception;
|
||||
use PasswordGenerator\Generator as PassGen;
|
||||
|
||||
class DriverExternalMock extends DriverSkeleton implements Driver {
|
||||
|
@ -22,7 +22,7 @@ class DriverExternalMock extends DriverSkeleton implements Driver {
|
|||
"userRightsSet" => Driver::FUNC_EXTERNAL,
|
||||
];
|
||||
|
||||
static public function create(\JKingWeb\NewsSync\RuntimeData $data): Driver {
|
||||
static public function create(\JKingWeb\Arsse\RuntimeData $data): Driver {
|
||||
return new static($data);
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ class DriverExternalMock extends DriverSkeleton implements Driver {
|
|||
}
|
||||
}
|
||||
|
||||
public function __construct(\JKingWeb\NewsSync\RuntimeData $data) {
|
||||
public function __construct(\JKingWeb\Arsse\RuntimeData $data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test\User;
|
||||
use JKingWeb\NewsSync\User\Driver;
|
||||
namespace JKingWeb\Arsse\Test\User;
|
||||
use JKingWeb\Arsse\User\Driver;
|
||||
|
||||
class DriverInternalMock extends Database implements Driver {
|
||||
|
||||
|
@ -20,7 +20,7 @@ class DriverInternalMock extends Database implements Driver {
|
|||
"userRightsSet" => Driver::FUNC_INTERNAL,
|
||||
];
|
||||
|
||||
static public function create(\JKingWeb\NewsSync\RuntimeData $data): Driver {
|
||||
static public function create(\JKingWeb\Arsse\RuntimeData $data): Driver {
|
||||
return new static($data);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ class DriverInternalMock extends Database implements Driver {
|
|||
}
|
||||
}
|
||||
|
||||
public function __construct(\JKingWeb\NewsSync\RuntimeData $data) {
|
||||
public function __construct(\JKingWeb\Arsse\RuntimeData $data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Test\User;
|
||||
use JKingWeb\NewsSync\Lang;
|
||||
use JKingWeb\NewsSync\User\Driver;
|
||||
use JKingWeb\NewsSync\User\Exception;
|
||||
use JKingWeb\NewsSync\User\ExceptionAuthz;
|
||||
namespace JKingWeb\Arsse\Test\User;
|
||||
use JKingWeb\Arsse\Lang;
|
||||
use JKingWeb\Arsse\User\Driver;
|
||||
use JKingWeb\Arsse\User\Exception;
|
||||
use JKingWeb\Arsse\User\ExceptionAuthz;
|
||||
use PasswordGenerator\Generator as PassGen;
|
||||
|
||||
abstract class DriverSkeleton {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
namespace JKingWeb\NewsSync;
|
||||
namespace JKingWeb\Arsse;
|
||||
const INSTALL = true;
|
||||
require_once "../bootstrap.php";
|
||||
|
||||
|
|
Loading…
Reference in a new issue