1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-22 13:12:41 +00:00

Add export-to-file wrapper for OPML

This commit is contained in:
J. King 2019-04-01 16:54:14 -04:00
parent 35e79d53a9
commit deea294f8a
7 changed files with 128 additions and 0 deletions

View file

@ -86,6 +86,8 @@ abstract class AbstractException extends \Exception {
"Feed/Exception.xmlEntity" => 10512,
"Feed/Exception.subscriptionNotFound" => 10521,
"Feed/Exception.unsupportedFeedFormat" => 10522,
"ImportExport/Exception.fileUnwritable" => 10604,
"ImportExport/Exception.fileUncreatable" => 10605,
];
public function __construct(string $msgID = "", $vars = null, \Throwable $e = null) {

View file

@ -0,0 +1,10 @@
<?php
/** @license MIT
* Copyright 2017 J. King, Dustin Wilson et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace JKingWeb\Arsse\ImportExport;
class Exception extends \JKingWeb\Arsse\AbstractException {
}

View file

@ -7,9 +7,13 @@ declare(strict_types=1);
namespace JKingWeb\Arsse\ImportExport;
use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\User\Exception as UserException;
class OPML {
public function export(string $user, bool $flat = false): string {
if (!Arsse::$user->exists($user)) {
throw new UserException("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
}
$tags = [];
$folders = [];
$parents = [0 => null];
@ -68,4 +72,14 @@ class OPML {
// return the serialization
return $document->saveXML();
}
public function exportFile(string $file, string $user, bool $flat = false): bool {
$data = $this->export($user, $flat);
if (!@file_put_contents($file, $data)) {
// if it fails throw an exception
$err = file_exists($file) ? "fileUnwritable" : "fileUncreatable";
throw new Exception($err, ['file' => $file, 'format' => str_replace(__NAMESPACE__."\\", "", __CLASS__)]);
}
return true;
}
}

View file

@ -155,4 +155,14 @@ return [
'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.unsupportedFeedFormat' => 'Feed "{url}" is of an unsupported format',
'Exception.JKingWeb/Arsse/ImportExport/Exception.fileUncreatable' =>
'Insufficient permissions to write {type, select,
OPML {OPML}
other {"{type}"}
} export to file "{file}"',
'Exception.JKingWeb/Arsse/ImportExport/Exception.fileUnwritable' =>
'Insufficient permissions to write {type, select,
OPML {OPML}
other {"{type}"}
} export to existing file "{file}"',
];

View file

@ -79,7 +79,10 @@ OPML_EXPORT_SERIALIZATION;
OPML_EXPORT_SERIALIZATION;
public function setUp() {
self::clearData();
Arsse::$db = \Phake::mock(\JKingWeb\Arsse\Database::class);
Arsse::$user = \Phake::mock(\JKingWeb\Arsse\User::class);
\Phake::when(Arsse::$user)->exists->thenReturn(true);
}
public function testExportToOpml() {
@ -95,4 +98,10 @@ OPML_EXPORT_SERIALIZATION;
\Phake::when(Arsse::$db)->tagSummarize("john.doe@example.com")->thenReturn(new Result($this->tags));
$this->assertXmlStringEqualsXmlString($this->serializationFlat, (new OPML)->export("john.doe@example.com", true));
}
public function testExportToOpmlAMissingUser() {
\Phake::when(Arsse::$user)->exists->thenReturn(false);
$this->assertException("doesNotExist", "User");
(new OPML)->export("john.doe@example.com");
}
}

View file

@ -0,0 +1,82 @@
<?php
/** @license MIT
* Copyright 2017 J. King, Dustin Wilson et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace JKingWeb\Arsse\TestCase\ImportExport;
use JKingWeb\Arsse\ImportExport\OPML;
use JKingWeb\Arsse\ImportExport\Exception;
use org\bovigo\vfs\vfsStream;
/** @covers \JKingWeb\Arsse\ImportExport\OPML<extended> */
class TestOPMLFile extends \JKingWeb\Arsse\Test\AbstractTest {
protected $vfs;
protected $path;
protected $opml;
public function setUp() {
self::clearData();
// 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");
$this->vfs = vfsStream::setup("root", null, [
'exportGoodFile' => "",
'exportGoodDir' => [],
'exportBadFile' => "",
'exportBadDir' => [],
]);
$this->path = $this->vfs->url()."/";
// make the "bad" entries inaccessible
chmod($this->path."exportBadFile", 0000);
chmod($this->path."exportBadDir", 0000);
}
public function tearDown() {
$this->path = null;
$this->vfs = null;
$this->opml = null;
self::clearData();
}
/** @dataProvider provideFileExports */
public function testExportOpmlToAFile(string $file, string $user, bool $flat, $exp) {
$path = $this->path.$file;
try {
if ($exp instanceof \JKingWeb\Arsse\AbstractException) {
$this->assertException($exp);
$this->opml->exportFile($path, $user, $flat);
} else {
$this->assertSame($exp, $this->opml->exportFile($path, $user, $flat));
$this->assertSame("OPML_FILE", $this->vfs->getChild($file)->getContent());
}
} finally {
\Phake::verify($this->opml)->export($user, $flat);
}
}
public function provideFileExports() {
$createException = new Exception("fileUncreatable");
$writeException = new Exception("fileUnwritable");
return [
["exportGoodFile", "john.doe@example.com", true, true],
["exportGoodFile", "john.doe@example.com", false, true],
["exportGoodFile", "jane.doe@example.com", true, true],
["exportGoodFile", "jane.doe@example.com", false, true],
["exportGoodDir/file", "john.doe@example.com", true, true],
["exportGoodDir/file", "john.doe@example.com", false, true],
["exportGoodDir/file", "jane.doe@example.com", true, true],
["exportGoodDir/file", "jane.doe@example.com", false, true],
["exportBadFile", "john.doe@example.com", true, $writeException],
["exportBadFile", "john.doe@example.com", false, $writeException],
["exportBadFile", "jane.doe@example.com", true, $writeException],
["exportBadFile", "jane.doe@example.com", false, $writeException],
["exportBadDir/file", "john.doe@example.com", true, $createException],
["exportBadDir/file", "john.doe@example.com", false, $createException],
["exportBadDir/file", "jane.doe@example.com", true, $createException],
["exportBadDir/file", "jane.doe@example.com", false, $createException],
];
}
}

View file

@ -115,6 +115,7 @@
</testsuite>
<testsuite name="Import/Export">
<file>cases/ImportExport/TestOPML.php</file>
<file>cases/ImportExport/TestOPMLFile.php</file>
</testsuite>
</testsuites>
</phpunit>