diff --git a/lib/ImportExport/OPML.php b/lib/ImportExport/OPML.php
index a45d4e1a..5c633b4b 100644
--- a/lib/ImportExport/OPML.php
+++ b/lib/ImportExport/OPML.php
@@ -38,9 +38,9 @@ class OPML {
// start a transaction for atomic rollback
$tr = Arsse::$db->begin();
// get current state of database
- $foldersDb = iterator_to_array(Arsse::$db->folderList(Arsse::$user->id));
- $feedsDb = iterator_to_array(Arsse::$db->subscriptionList(Arsse::$user->id));
- $tagsDb = iterator_to_array(Arsse::$db->tagList(Arsse::$user->id));
+ $foldersDb = iterator_to_array(Arsse::$db->folderList($user));
+ $feedsDb = iterator_to_array(Arsse::$db->subscriptionList($user));
+ $tagsDb = iterator_to_array(Arsse::$db->tagList($user));
// reconcile folders
$folderMap = [0 => 0];
foreach ($folders as $id => $f) {
@@ -54,7 +54,7 @@ class OPML {
}
if (!isset($folderMap[$id])) {
// if no existing folder exists, add one
- $folderMap[$id] = Arsse::$db->folderAdd(Arsse::$user->id, ['name' => $f['name'], 'parent' -> $parent]);
+ $folderMap[$id] = Arsse::$db->folderAdd($user, ['name' => $f['name'], 'parent' -> $parent]);
}
}
// process newsfeed subscriptions
@@ -74,11 +74,11 @@ class OPML {
}
if (!$found) {
// if no subscription exists, add one
- $feedMap[$f['id']] = Arsse::$db->subscriptionAdd(Arsse::$user->id, $f['url']);
+ $feedMap[$f['id']] = Arsse::$db->subscriptionAdd($user, $f['url']);
}
if (!$found || $replace) {
// set the subscription's properties, if this is a new feed or we're doing a full replacement
- Arsse::$db->subscriptionPropertiesSet(Arsse::$user->id, $feedMap[$f['id']], ['title' => $title, 'folder' => $folder]);
+ Arsse::$db->subscriptionPropertiesSet($user, $feedMap[$f['id']], ['title' => $title, 'folder' => $folder]);
// compile the set of used tags, if this is a new feed or we're doing a full replacement
foreach ($f['tags'] as $t) {
if (!strlen(trim($t))) {
@@ -106,29 +106,29 @@ class OPML {
}
if (!$found) {
// add the tag if it wasn't found
- Arsse::$db->tagAdd(Arsse::$user->id, ['name' => $tag]);
+ Arsse::$db->tagAdd($user, ['name' => $tag]);
}
- Arsse::$db->tagSubscriptionsSet(Arsse::$user->id, $tag, $subs, $mode, true);
+ Arsse::$db->tagSubscriptionsSet($user, $tag, $subs, $mode, true);
}
// finally, if we're performing a replacement, delete any subscriptions, folders, or tags which were not present in the import
if ($replace) {
foreach (array_diff(array_column($feedsDb, "id"), $feedMap) as $id) {
try {
- Arsse::$db->subscriptionRemove(Arsse::$user->id, $id);
+ Arsse::$db->subscriptionRemove($user, $id);
} catch (InputException $e) {
// ignore errors
}
}
foreach (array_diff(array_column($foldersDb, "id"), $folderMap) as $id) {
try {
- Arsse::$db->folderRemove(Arsse::$user->id, $id);
+ Arsse::$db->folderRemove($user, $id);
} catch (InputException $e) {
// ignore errors
}
}
foreach (array_diff(array_column($tagsDb, "name"), array_keys($tagMap)) as $id) {
try {
- Arsse::$db->tagRemove(Arsse::$user->id, $id, true);
+ Arsse::$db->tagRemove($user, $id, true);
} catch (InputException $e) {
// ignore errors
}
@@ -287,7 +287,7 @@ class OPML {
return true;
}
- public function imortFile(string $file, string $user, bool $flat = false, bool $replace): bool {
+ public function importFile(string $file, string $user, bool $flat = false, bool $replace): bool {
$data = @file_get_contents($file);
if ($data === false) {
// if it fails throw an exception
diff --git a/tests/cases/ImportExport/TestOPMLFile.php b/tests/cases/ImportExport/TestOPMLFile.php
index 37b9e61d..35147ef8 100644
--- a/tests/cases/ImportExport/TestOPMLFile.php
+++ b/tests/cases/ImportExport/TestOPMLFile.php
@@ -21,16 +21,20 @@ class TestOPMLFile extends \JKingWeb\Arsse\Test\AbstractTest {
// create a mock OPML processor with stubbed underlying import/export routines
$this->opml = \Phake::partialMock(OPML::class);
\Phake::when($this->opml)->export->thenReturn("OPML_FILE");
+ \Phake::when($this->opml)->import->thenReturn(true);
$this->vfs = vfsStream::setup("root", null, [
'exportGoodFile' => "",
'exportGoodDir' => [],
'exportBadFile' => "",
'exportBadDir' => [],
+ 'importGoodFile' => "",
+ 'importBadFile' => "",
]);
$this->path = $this->vfs->url()."/";
// make the "bad" entries inaccessible
chmod($this->path."exportBadFile", 0000);
chmod($this->path."exportBadDir", 0000);
+ chmod($this->path."importBadFile", 0000);
}
public function tearDown() {
@@ -78,4 +82,50 @@ class TestOPMLFile extends \JKingWeb\Arsse\Test\AbstractTest {
["exportBadDir/file", "jane.doe@example.com", false, $createException],
];
}
+
+ /** @dataProvider provideFileImports */
+ public function testImportFromOpmlFile(string $file, string $user, bool $flat, bool $replace, $exp) {
+ $path = $this->path.$file;
+ try {
+ if ($exp instanceof \JKingWeb\Arsse\AbstractException) {
+ $this->assertException($exp);
+ $this->opml->importFile($path, $user, $flat, $replace);
+ } else {
+ $this->assertSame($exp, $this->opml->importFile($path, $user, $flat, $replace));
+ }
+ } finally {
+ \Phake::verify($this->opml, \Phake::times((int) ($exp === true)))->import($user, "", $flat, $replace);
+ }
+ }
+
+ public function provideFileImports() {
+ $missingException = new Exception("fileMissing");
+ $permissionException = new Exception("fileUnreadable");
+ return [
+ ["importGoodFile", "john.doe@example.com", true, true, true],
+ ["importBadFile", "john.doe@example.com", true, true, $permissionException],
+ ["importNonFile", "john.doe@example.com", true, true, $missingException],
+ ["importGoodFile", "john.doe@example.com", true, false, true],
+ ["importBadFile", "john.doe@example.com", true, false, $permissionException],
+ ["importNonFile", "john.doe@example.com", true, false, $missingException],
+ ["importGoodFile", "john.doe@example.com", false, true, true],
+ ["importBadFile", "john.doe@example.com", false, true, $permissionException],
+ ["importNonFile", "john.doe@example.com", false, true, $missingException],
+ ["importGoodFile", "john.doe@example.com", false, false, true],
+ ["importBadFile", "john.doe@example.com", false, false, $permissionException],
+ ["importNonFile", "john.doe@example.com", false, false, $missingException],
+ ["importGoodFile", "jane.doe@example.com", true, true, true],
+ ["importBadFile", "jane.doe@example.com", true, true, $permissionException],
+ ["importNonFile", "jane.doe@example.com", true, true, $missingException],
+ ["importGoodFile", "jane.doe@example.com", true, false, true],
+ ["importBadFile", "jane.doe@example.com", true, false, $permissionException],
+ ["importNonFile", "jane.doe@example.com", true, false, $missingException],
+ ["importGoodFile", "jane.doe@example.com", false, true, true],
+ ["importBadFile", "jane.doe@example.com", false, true, $permissionException],
+ ["importNonFile", "jane.doe@example.com", false, true, $missingException],
+ ["importGoodFile", "jane.doe@example.com", false, false, true],
+ ["importBadFile", "jane.doe@example.com", false, false, $permissionException],
+ ["importNonFile", "jane.doe@example.com", false, false, $missingException],
+ ];
+ }
}