mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
Merge master
This commit is contained in:
parent
5488b994f7
commit
0a0aabe4ed
19 changed files with 135 additions and 75 deletions
31
.gitattributes
vendored
31
.gitattributes
vendored
|
@ -1,22 +1,13 @@
|
||||||
# Auto detect text files and perform LF normalization
|
* text=auto encoding=utf-8
|
||||||
* text=auto
|
|
||||||
|
|
||||||
# Custom for Visual Studio
|
*.html diff=html
|
||||||
*.cs diff=csharp
|
*.php diff=php
|
||||||
*.sln merge=union
|
*.bat eol=crlf
|
||||||
*.csproj merge=union
|
.gitignore -eol
|
||||||
*.vbproj merge=union
|
|
||||||
*.fsproj merge=union
|
|
||||||
*.dbproj merge=union
|
|
||||||
|
|
||||||
# Standard to msysgit
|
|
||||||
*.doc diff=astextplain
|
tests/ export-ignore
|
||||||
*.DOC diff=astextplain
|
.* export-ignore
|
||||||
*.docx diff=astextplain
|
build.xml export-ignore
|
||||||
*.DOCX diff=astextplain
|
composer.* export-ignore
|
||||||
*.dot diff=astextplain
|
phpdoc.* export-ignore
|
||||||
*.DOT diff=astextplain
|
|
||||||
*.pdf diff=astextplain
|
|
||||||
*.PDF diff=astextplain
|
|
||||||
*.rtf diff=astextplain
|
|
||||||
*.RTF diff=astextplain
|
|
||||||
|
|
53
.gitignore
vendored
53
.gitignore
vendored
|
@ -1,48 +1,45 @@
|
||||||
#dependencies
|
|
||||||
vendor/
|
|
||||||
|
|
||||||
#temp files
|
# Temporary files and dependencies
|
||||||
|
|
||||||
|
vendor/
|
||||||
documentation/
|
documentation/
|
||||||
tests/coverage
|
tests/coverage/
|
||||||
|
build/
|
||||||
arsse.db*
|
arsse.db*
|
||||||
config.php
|
config.php
|
||||||
.php_cs.cache
|
.php_cs.cache
|
||||||
build
|
|
||||||
|
|
||||||
# Windows image file caches
|
|
||||||
|
|
||||||
|
|
||||||
|
# Windows files
|
||||||
|
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
ehthumbs.db
|
ehthumbs.db
|
||||||
|
|
||||||
# Folder config file
|
|
||||||
Desktop.ini
|
Desktop.ini
|
||||||
|
|
||||||
# Recycle Bin used on file shares
|
|
||||||
$RECYCLE.BIN/
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
# Windows Installer files
|
|
||||||
*.cab
|
|
||||||
*.msi
|
|
||||||
*.msm
|
|
||||||
*.msp
|
|
||||||
|
|
||||||
# =========================
|
# macOS files
|
||||||
# Operating System Files
|
|
||||||
# =========================
|
|
||||||
|
|
||||||
# OSX
|
|
||||||
# =========================
|
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.AppleDouble
|
.AppleDouble
|
||||||
.LSOverride
|
.LSOverride
|
||||||
|
|
||||||
# Icon must ends with two \r.
|
|
||||||
Icon
|
Icon
|
||||||
|
|
||||||
|
|
||||||
# Thumbnails
|
|
||||||
._*
|
._*
|
||||||
|
|
||||||
# Files that might appear on external disk
|
|
||||||
.Spotlight-V100
|
.Spotlight-V100
|
||||||
.Trashes
|
.Trashes
|
||||||
|
|
||||||
|
# archives
|
||||||
|
|
||||||
|
*.zip
|
||||||
|
*.7z
|
||||||
|
*.tar.gz
|
||||||
|
*.tgz
|
||||||
|
*.deb
|
||||||
|
*.rpm
|
||||||
|
*.dmg
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
12
CHANGELOG
Normal file
12
CHANGELOG
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Version 0.1.1 (2017-09-30)
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
- Perform feed discovery like NextCloud News does
|
||||||
|
- Respond correctly to HEAD requests
|
||||||
|
- Various minor fixes
|
||||||
|
|
||||||
|
Version 0.1.0 (2017-08-29)
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Initial release
|
|
@ -4,7 +4,7 @@ namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
const BASE = __DIR__.DIRECTORY_SEPARATOR;
|
const BASE = __DIR__.DIRECTORY_SEPARATOR;
|
||||||
const NS_BASE = __NAMESPACE__."\\";
|
const NS_BASE = __NAMESPACE__."\\";
|
||||||
const VERSION = "0.1.0";
|
const VERSION = "0.1.1";
|
||||||
|
|
||||||
require_once BASE."vendor".DIRECTORY_SEPARATOR."autoload.php";
|
require_once BASE."vendor".DIRECTORY_SEPARATOR."autoload.php";
|
||||||
ignore_user_abort(true);
|
ignore_user_abort(true);
|
|
@ -11,6 +11,7 @@
|
||||||
<include name="composer.*"/>
|
<include name="composer.*"/>
|
||||||
<include name="arsse.php"/>
|
<include name="arsse.php"/>
|
||||||
<include name="bootstrap.php"/>
|
<include name="bootstrap.php"/>
|
||||||
|
<include name="CHANGELOG"/>
|
||||||
<include name="LICENSE"/>
|
<include name="LICENSE"/>
|
||||||
<include name="README.md"/>
|
<include name="README.md"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
|
|
1
dist/nginx-fcgi.conf
vendored
1
dist/nginx-fcgi.conf
vendored
|
@ -10,3 +10,4 @@ fastcgi_param CONTENT_TYPE $content_type;
|
||||||
fastcgi_param CONTENT_LENGTH $content_length;
|
fastcgi_param CONTENT_LENGTH $content_length;
|
||||||
fastcgi_param REQUEST_URI $request_uri;
|
fastcgi_param REQUEST_URI $request_uri;
|
||||||
fastcgi_param HTTPS $https if_not_empty;
|
fastcgi_param HTTPS $https if_not_empty;
|
||||||
|
fastcgi_param REMOTE_USER $remote_user;
|
|
@ -84,7 +84,7 @@ USAGE_TEXT;
|
||||||
public function userAdd(string $user, string $password = null): int {
|
public function userAdd(string $user, string $password = null): int {
|
||||||
$passwd = Arsse::$user->add($user, $password);
|
$passwd = Arsse::$user->add($user, $password);
|
||||||
if (is_null($password)) {
|
if (is_null($password)) {
|
||||||
echo $passwd;
|
echo $passwd.\PHP_EOL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -459,7 +459,7 @@ class Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function subscriptionAdd(string $user, string $url, string $fetchUser = "", string $fetchPassword = ""): int {
|
public function subscriptionAdd(string $user, string $url, string $fetchUser = "", string $fetchPassword = "", bool $discover = true): int {
|
||||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
}
|
}
|
||||||
|
@ -470,7 +470,7 @@ class Database {
|
||||||
$feedID = $this->db->prepare('INSERT INTO arsse_feeds(url,username,password) values(?,?,?)', 'str', 'str', 'str')->run($url, $fetchUser, $fetchPassword)->lastId();
|
$feedID = $this->db->prepare('INSERT INTO arsse_feeds(url,username,password) values(?,?,?)', 'str', 'str', 'str')->run($url, $fetchUser, $fetchPassword)->lastId();
|
||||||
try {
|
try {
|
||||||
// perform an initial update on the newly added feed
|
// perform an initial update on the newly added feed
|
||||||
$this->feedUpdate($feedID, true);
|
$this->feedUpdate($feedID, true, $discover);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
// if the update fails, delete the feed we just added
|
// if the update fails, delete the feed we just added
|
||||||
$this->db->prepare('DELETE from arsse_feeds where id is ?', 'int')->run($feedID);
|
$this->db->prepare('DELETE from arsse_feeds where id is ?', 'int')->run($feedID);
|
||||||
|
@ -601,7 +601,7 @@ class Database {
|
||||||
return array_column($feeds, 'id');
|
return array_column($feeds, 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function feedUpdate($feedID, bool $throwError = false): bool {
|
public function feedUpdate($feedID, bool $throwError = false, bool $discover = false): bool {
|
||||||
$tr = $this->db->begin();
|
$tr = $this->db->begin();
|
||||||
// check to make sure the feed exists
|
// check to make sure the feed exists
|
||||||
if (!ValueInfo::id($feedID)) {
|
if (!ValueInfo::id($feedID)) {
|
||||||
|
@ -617,7 +617,7 @@ class Database {
|
||||||
// here. When an exception is thrown it should update the database with the
|
// here. When an exception is thrown it should update the database with the
|
||||||
// error instead of failing; if other exceptions are thrown, we should simply roll back
|
// error instead of failing; if other exceptions are thrown, we should simply roll back
|
||||||
try {
|
try {
|
||||||
$feed = new Feed((int) $feedID, $f['url'], (string) Date::transform($f['modified'], "http", "sql"), $f['etag'], $f['username'], $f['password'], $scrape);
|
$feed = new Feed((int) $feedID, $f['url'], (string) Date::transform($f['modified'], "http", "sql"), $f['etag'], $f['username'], $f['password'], $scrape, $discover);
|
||||||
if (!$feed->modified) {
|
if (!$feed->modified) {
|
||||||
// if the feed hasn't changed, just compute the next fetch time and record it
|
// if the feed hasn't changed, just compute the next fetch time and record it
|
||||||
$this->db->prepare("UPDATE arsse_feeds SET updated = CURRENT_TIMESTAMP, next_fetch = ? WHERE id is ?", 'datetime', 'int')->run($feed->nextFetch, $feedID);
|
$this->db->prepare("UPDATE arsse_feeds SET updated = CURRENT_TIMESTAMP, next_fetch = ? WHERE id is ?", 'datetime', 'int')->run($feed->nextFetch, $feedID);
|
||||||
|
|
13
lib/Feed.php
13
lib/Feed.php
|
@ -21,7 +21,7 @@ class Feed {
|
||||||
public $newItems = [];
|
public $newItems = [];
|
||||||
public $changedItems = [];
|
public $changedItems = [];
|
||||||
|
|
||||||
public function __construct(int $feedID = null, string $url, string $lastModified = '', string $etag = '', string $username = '', string $password = '', bool $scrape = false) {
|
public function __construct(int $feedID = null, string $url, string $lastModified = '', string $etag = '', string $username = '', string $password = '', bool $scrape = false, bool $discover = false) {
|
||||||
// set the configuration
|
// set the configuration
|
||||||
$userAgent = Arsse::$conf->fetchUserAgentString ?? sprintf('Arsse/%s (%s %s; %s; https://code.jkingweb.ca/jking/arsse) PicoFeed (https://github.com/fguillot/picoFeed)',
|
$userAgent = Arsse::$conf->fetchUserAgentString ?? sprintf('Arsse/%s (%s %s; %s; https://code.jkingweb.ca/jking/arsse) PicoFeed (https://github.com/fguillot/picoFeed)',
|
||||||
VERSION, // Arsse version
|
VERSION, // Arsse version
|
||||||
|
@ -36,7 +36,7 @@ class Feed {
|
||||||
$this->config->setClientUserAgent($userAgent);
|
$this->config->setClientUserAgent($userAgent);
|
||||||
$this->config->setGrabberUserAgent($userAgent);
|
$this->config->setGrabberUserAgent($userAgent);
|
||||||
// fetch the feed
|
// fetch the feed
|
||||||
$this->download($url, $lastModified, $etag, $username, $password);
|
$this->download($url, $lastModified, $etag, $username, $password, $discover);
|
||||||
// format the HTTP Last-Modified date returned
|
// format the HTTP Last-Modified date returned
|
||||||
$lastMod = $this->resource->getLastModified();
|
$lastMod = $this->resource->getLastModified();
|
||||||
if (strlen($lastMod)) {
|
if (strlen($lastMod)) {
|
||||||
|
@ -65,10 +65,11 @@ class Feed {
|
||||||
$this->nextFetch = $this->computeNextFetch();
|
$this->nextFetch = $this->computeNextFetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function download(string $url, string $lastModified = '', string $etag = '', string $username = '', string $password = ''): bool {
|
protected function download(string $url, string $lastModified, string $etag, string $username, string $password, bool $discover): bool {
|
||||||
|
$action = $discover ? "discover" : "download";
|
||||||
try {
|
try {
|
||||||
$this->reader = new Reader($this->config);
|
$this->reader = new Reader($this->config);
|
||||||
$this->resource = $this->reader->download($url, $lastModified, $etag, $username, $password);
|
$this->resource = $this->reader->$action($url, $lastModified, $etag, $username, $password);
|
||||||
} catch (PicoFeedException $e) {
|
} catch (PicoFeedException $e) {
|
||||||
throw new Feed\Exception($url, $e);
|
throw new Feed\Exception($url, $e);
|
||||||
}
|
}
|
||||||
|
@ -361,13 +362,13 @@ class Feed {
|
||||||
|
|
||||||
protected function computeLastModified() {
|
protected function computeLastModified() {
|
||||||
if (!$this->modified) {
|
if (!$this->modified) {
|
||||||
return $this->lastModified;
|
return $this->lastModified; // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
$dates = $this->gatherDates();
|
$dates = $this->gatherDates();
|
||||||
if (sizeof($dates)) {
|
if (sizeof($dates)) {
|
||||||
return Date::normalize($dates[0]);
|
return Date::normalize($dates[0]);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null; // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,14 @@ class REST {
|
||||||
$req->refreshURL();
|
$req->refreshURL();
|
||||||
$class = $this->apis[$api]['class'];
|
$class = $this->apis[$api]['class'];
|
||||||
$drv = new $class();
|
$drv = new $class();
|
||||||
|
if ($req->head) {
|
||||||
|
$res = $drv->dispatch($req);
|
||||||
|
$res->head = true;
|
||||||
|
return $res;
|
||||||
|
} else {
|
||||||
return $drv->dispatch($req);
|
return $drv->dispatch($req);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function apiMatch(string $url, array $map): string {
|
public function apiMatch(string $url, array $map): string {
|
||||||
// sort the API list so the longest URL prefixes come first
|
// sort the API list so the longest URL prefixes come first
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Versions implements \JKingWeb\Arsse\REST\Handler {
|
||||||
public function dispatch(\JKingWeb\Arsse\REST\Request $req): Response {
|
public function dispatch(\JKingWeb\Arsse\REST\Request $req): Response {
|
||||||
// if a method other than GET was used, this is an error
|
// if a method other than GET was used, this is an error
|
||||||
if ($req->method != "GET") {
|
if ($req->method != "GET") {
|
||||||
return new Response(405);
|
return new Response(405, "", "", ["Allow: GET"]);
|
||||||
}
|
}
|
||||||
if (preg_match("<^/?$>", $req->path)) {
|
if (preg_match("<^/?$>", $req->path)) {
|
||||||
// if the request path is an empty string or just a slash, return the supported versions
|
// if the request path is an empty string or just a slash, return the supported versions
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace JKingWeb\Arsse\REST;
|
||||||
|
|
||||||
class Request {
|
class Request {
|
||||||
public $method = "GET";
|
public $method = "GET";
|
||||||
|
public $head = false;
|
||||||
public $url = "";
|
public $url = "";
|
||||||
public $path ="";
|
public $path ="";
|
||||||
public $paths = [];
|
public $paths = [];
|
||||||
|
@ -26,6 +27,10 @@ class Request {
|
||||||
$this->url = $url;
|
$this->url = $url;
|
||||||
$this->body = $body;
|
$this->body = $body;
|
||||||
$this->type = $contentType;
|
$this->type = $contentType;
|
||||||
|
if ($this->method=="HEAD") {
|
||||||
|
$this->head = true;
|
||||||
|
$this->method = "GET";
|
||||||
|
}
|
||||||
$this->refreshURL();
|
$this->refreshURL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ class Response {
|
||||||
const T_XML = "application/xml";
|
const T_XML = "application/xml";
|
||||||
const T_TEXT = "text/plain";
|
const T_TEXT = "text/plain";
|
||||||
|
|
||||||
|
public $head = false;
|
||||||
public $code;
|
public $code;
|
||||||
public $payload;
|
public $payload;
|
||||||
public $type;
|
public $type;
|
||||||
|
@ -24,15 +25,11 @@ class Response {
|
||||||
|
|
||||||
public function output() {
|
public function output() {
|
||||||
if (!headers_sent()) {
|
if (!headers_sent()) {
|
||||||
try {
|
foreach ($this->fields as $field) {
|
||||||
$statusText = Arsse::$lang->msg("HTTP.Status.".$this->code);
|
header($field);
|
||||||
} catch (\JKingWeb\Arsse\Lang\Exception $e) {
|
|
||||||
$statusText = "";
|
|
||||||
}
|
}
|
||||||
header("Status: ".$this->code." ".$statusText);
|
|
||||||
$body = "";
|
$body = "";
|
||||||
if (!is_null($this->payload)) {
|
if (!is_null($this->payload)) {
|
||||||
header("Content-Type: ".$this->type);
|
|
||||||
switch ($this->type) {
|
switch ($this->type) {
|
||||||
case self::T_JSON:
|
case self::T_JSON:
|
||||||
$body = (string) json_encode($this->payload, \JSON_PRETTY_PRINT);
|
$body = (string) json_encode($this->payload, \JSON_PRETTY_PRINT);
|
||||||
|
@ -42,10 +39,21 @@ class Response {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($this->fields as $field) {
|
if (strlen($body)) {
|
||||||
header($field);
|
header("Content-Type: ".$this->type);
|
||||||
|
header("Content-Length: ".strlen($body));
|
||||||
|
} elseif ($this->code==200) {
|
||||||
|
$this->code = 204;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
$statusText = Arsse::$lang->msg("HTTP.Status.".$this->code);
|
||||||
|
} catch (\JKingWeb\Arsse\Lang\Exception $e) {
|
||||||
|
$statusText = "";
|
||||||
|
}
|
||||||
|
header("Status: ".$this->code." ".$statusText);
|
||||||
|
if (!$this->head) {
|
||||||
echo $body;
|
echo $body;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new REST\Exception("headersSent");
|
throw new REST\Exception("headersSent");
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,15 @@ class TestFeed extends Test\AbstractTest {
|
||||||
$this->assertSame($categories, $f->data->items[5]->categories);
|
$this->assertSame($categories, $f->data->items[5]->categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDiscoverAFeedSuccessfully() {
|
||||||
|
$this->assertInstanceOf(Feed::class, new Feed(null, $this->base."Discovery/Valid", "", "", "", "", false, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDiscoverAFeedUnsuccessfully() {
|
||||||
|
$this->assertException("subscriptionNotFound", "Feed");
|
||||||
|
new Feed(null, $this->base."Discovery/Invalid", "", "", "", "", false, true);
|
||||||
|
}
|
||||||
|
|
||||||
public function testParseEntityExpansionAttack() {
|
public function testParseEntityExpansionAttack() {
|
||||||
$this->assertException("xmlEntity", "Feed");
|
$this->assertException("xmlEntity", "Feed");
|
||||||
new Feed(null, $this->base."Parsing/XEEAttack");
|
new Feed(null, $this->base."Parsing/XEEAttack");
|
||||||
|
|
|
@ -26,7 +26,7 @@ class TestNCNVersionDiscovery extends Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUseIncorrectMethod() {
|
public function testUseIncorrectMethod() {
|
||||||
$exp = new Response(405);
|
$exp = new Response(405, "", "", ["Allow: GET"]);
|
||||||
$h = new REST\NextCloudNews\Versions();
|
$h = new REST\NextCloudNews\Versions();
|
||||||
$req = new Request("POST", "/");
|
$req = new Request("POST", "/");
|
||||||
$res = $h->dispatch($req);
|
$res = $h->dispatch($req);
|
||||||
|
|
12
tests/docroot/Feed/Discovery/Feed.php
Normal file
12
tests/docroot/Feed/Discovery/Feed.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php return [
|
||||||
|
'mime' => "application/rss+xml",
|
||||||
|
'content' => <<<MESSAGE_BODY
|
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<channel>
|
||||||
|
<title>Test feed</title>
|
||||||
|
<link>http://example.com/</link>
|
||||||
|
<description>Example newsfeed title</description>
|
||||||
|
</channel>
|
||||||
|
</rss>
|
||||||
|
MESSAGE_BODY
|
||||||
|
];
|
8
tests/docroot/Feed/Discovery/Invalid.php
Normal file
8
tests/docroot/Feed/Discovery/Invalid.php
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?php return [
|
||||||
|
'mime' => "text/html",
|
||||||
|
'content' => <<<MESSAGE_BODY
|
||||||
|
<html>
|
||||||
|
<title>Example article</title>
|
||||||
|
</html>
|
||||||
|
MESSAGE_BODY
|
||||||
|
];
|
9
tests/docroot/Feed/Discovery/Valid.php
Normal file
9
tests/docroot/Feed/Discovery/Valid.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php return [
|
||||||
|
'mime' => "text/html",
|
||||||
|
'content' => <<<MESSAGE_BODY
|
||||||
|
<html>
|
||||||
|
<title>Example article</title>
|
||||||
|
<link rel="alternate" type="application/rss+xml" href="http://localhost:8000/Feed/Discovery/Feed">
|
||||||
|
</html>
|
||||||
|
MESSAGE_BODY
|
||||||
|
];
|
|
@ -135,7 +135,7 @@ trait SeriesSubscription {
|
||||||
Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
|
Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
|
||||||
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url));
|
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url));
|
||||||
Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd");
|
Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd");
|
||||||
Phake::verify(Arsse::$db)->feedUpdate($feedID, true);
|
Phake::verify(Arsse::$db)->feedUpdate($feedID, true, true);
|
||||||
$state = $this->primeExpectations($this->data, [
|
$state = $this->primeExpectations($this->data, [
|
||||||
'arsse_feeds' => ['id','url','username','password'],
|
'arsse_feeds' => ['id','url','username','password'],
|
||||||
'arsse_subscriptions' => ['id','owner','feed'],
|
'arsse_subscriptions' => ['id','owner','feed'],
|
||||||
|
@ -153,7 +153,7 @@ trait SeriesSubscription {
|
||||||
Arsse::$db->subscriptionAdd($this->user, $url);
|
Arsse::$db->subscriptionAdd($this->user, $url);
|
||||||
} catch (FeedException $e) {
|
} catch (FeedException $e) {
|
||||||
Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd");
|
Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd");
|
||||||
Phake::verify(Arsse::$db)->feedUpdate($feedID, true);
|
Phake::verify(Arsse::$db)->feedUpdate($feedID, true, true);
|
||||||
$state = $this->primeExpectations($this->data, [
|
$state = $this->primeExpectations($this->data, [
|
||||||
'arsse_feeds' => ['id','url','username','password'],
|
'arsse_feeds' => ['id','url','username','password'],
|
||||||
'arsse_subscriptions' => ['id','owner','feed'],
|
'arsse_subscriptions' => ['id','owner','feed'],
|
||||||
|
|
Loading…
Reference in a new issue