Browse Source

Insert folders into OPML before subscriptions

microsub
J. King 5 years ago
parent
commit
d63edf541f
  1. 22
      lib/ImportExport/OPML.php

22
lib/ImportExport/OPML.php

@ -10,9 +10,10 @@ use JKingWeb\Arsse\Arsse;
class OPML { class OPML {
public function export(string $user, bool $flat = false): string { public function export(string $user, bool $flat = false): string {
$tags = [];
$folders = []; $folders = [];
$parents = [0 => null]; $parents = [0 => null];
$tags = []; // create a base document
$document = new \DOMDocument("1.0", "utf-8"); $document = new \DOMDocument("1.0", "utf-8");
$document->formatOutput = true; $document->formatOutput = true;
$document->appendChild($document->createElement("opml")); $document->appendChild($document->createElement("opml"));
@ -20,10 +21,13 @@ class OPML {
$document->documentElement->appendChild($document->createElement("head")); $document->documentElement->appendChild($document->createElement("head"));
// create the "root folder" node (the body node, in OPML terms) // create the "root folder" node (the body node, in OPML terms)
$folders[0] = $document->createElement("body"); $folders[0] = $document->createElement("body");
// begin a transaction for read isolation
$transaction = Arsse::$db->begin(); $transaction = Arsse::$db->begin();
// gather up the list of tags for each subscription
foreach (Arsse::$db->tagSummarize($user) as $r) { foreach (Arsse::$db->tagSummarize($user) as $r) {
$sub = $r['subscription']; $sub = $r['subscription'];
$tag = $r['name']; $tag = $r['name'];
// strip out any commas in the tag name; sadly this is lossy as OPML has no escape mechanism
$tag = str_replace(",", "", $tag); $tag = str_replace(",", "", $tag);
if (!isset($tags[$sub])) { if (!isset($tags[$sub])) {
$tags[$sub] = []; $tags[$sub] = [];
@ -31,28 +35,36 @@ class OPML {
$tags[$sub][] = $tag; $tags[$sub][] = $tag;
} }
if (!$flat) { if (!$flat) {
// unless the output is requested flat, gather up the list of folders, using their database IDs as array indices
foreach (Arsse::$db->folderList($user) as $r) { foreach (Arsse::$db->folderList($user) as $r) {
// note the index of its parent folder for later tree construction
$parents[$r['id']] = $r['parent'] ?? 0; $parents[$r['id']] = $r['parent'] ?? 0;
// create a DOM node for each folder; we don't insert it yet
$el = $document->createElement("outline"); $el = $document->createElement("outline");
$el->setAttribute("text", $r['name']); $el->setAttribute("text", $r['name']);
$folders[$r['id']] = $el; $folders[$r['id']] = $el;
} }
// insert each folder into its parent node; for the root folder the parent is the document root node
foreach ($folders as $id => $el) {
$parent = $parents[$id] ?? $document->documentElement;
$parent->appendChild($el);
}
} }
// create a DOM node for each subscription and insert them directly into their folder DOM node
foreach (Arsse::$db->subscriptionList($user) as $r) { foreach (Arsse::$db->subscriptionList($user) as $r) {
$el = $document->createElement(("outline")); $el = $document->createElement(("outline"));
$el->setAttribute("text", $r['title']); $el->setAttribute("text", $r['title']);
$el->setAttribute("type", "rss"); $el->setAttribute("type", "rss");
$el->setAttribute("xmlUrl", $r['url']); $el->setAttribute("xmlUrl", $r['url']);
// include the category attribute only if there are tags
if (sizeof($tags[$r['id']])) { if (sizeof($tags[$r['id']])) {
$el->setAttribute("category", implode(",", $tags[$r['id']])); $el->setAttribute("category", implode(",", $tags[$r['id']]));
} }
// if flat output was requested subscriptions are inserted into the root folder
($folders[$r['folder'] ?? 0] ?? $folders[0])->appendChild($el); ($folders[$r['folder'] ?? 0] ?? $folders[0])->appendChild($el);
} }
// release the transaction
$transaction->rollback(); $transaction->rollback();
foreach ($folders as $id => $el) {
$parent = $parents[$id] ?? $document->documentElement;
$parent->appendChild($el);
}
// return the serialization // return the serialization
return $document->saveXML(); return $document->saveXML();
} }

Loading…
Cancel
Save