From ceecd583937dd7c7b4016ab7b77bbc7b09db8a41 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Sun, 21 Apr 2019 13:10:47 -0400 Subject: [PATCH] OPML parsing comments and minr fixes --- lib/Database.php | 2 +- lib/ImportExport/OPML.php | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/Database.php b/lib/Database.php index 24869078..df29fb46 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -700,7 +700,7 @@ class Database { * @param string $url The URL of the newsfeed or discovery source * @param string $fetchUser The user name required to access the newsfeed, if applicable * @param string $fetchPassword The password required to fetch the newsfeed, if applicable; this will be stored in cleartext - * @param boolean $discovery Whether to perform newsfeed discovery if $url points to an HTML document + * @param boolean $discover Whether to perform newsfeed discovery if $url points to an HTML document */ public function subscriptionAdd(string $user, string $url, string $fetchUser = "", string $fetchPassword = "", bool $discover = true): int { if (!Arsse::$user->authorize($user, __FUNCTION__)) { diff --git a/lib/ImportExport/OPML.php b/lib/ImportExport/OPML.php index 06ebfb38..5a1da742 100644 --- a/lib/ImportExport/OPML.php +++ b/lib/ImportExport/OPML.php @@ -11,7 +11,8 @@ use JKingWeb\Arsse\User\Exception as UserException; class OPML { public function import(string $user, string $opml, bool $flat = false, bool $replace = false): bool { - list($folders, $feeds) = $this->parse($opml, $flat); + list($feeds, $folders) = $this->parse($opml, $flat); + return true; } @@ -29,34 +30,47 @@ class OPML { $body = $body->item(0); $folders = []; $feeds = []; + // add the root folder to a map from folder DOM nodes to folder ID numbers $folderMap = new \SplObjectStorage; $folderMap[$body] = sizeof($folderMap); + // iterate through each node in the body $node = $body->firstChild; while ($node && $node != $body) { if ($node->nodeType == \XML_ELEMENT_NODE && $node->nodeName === "outline") { + // process any nodes which are outlines if ($node->getAttribute("type") === "rss") { + // feed nodes $url = $node->getAttribute("xmlUrl"); if (strlen($url)) { + // only process the node if it has a URL $title = $node->getAttribute("text"); $folder = $folderMap[$node->parentNode] ?? 0; $categories = $node->getAttribute("category"); if (strlen($categories)) { + // collapse and trim whitespace from category names, if any, splitting along commas $categories = array_map(function($v) { return trim(preg_replace("/\s+/g", " ", $v)); }, explode(",", $categories)); + } else { + $categories = []; } $feeds[] = ['url' => $url, 'title' => $title, 'folder' => $folder, 'categories' => $categories]; } + // skip any child nodes of a feed outline-entry $node = $node->nextSibling ?: $node->parentNode; } else { + // any outline entries which are not feeds are treated as folders if (!$flat) { + // only process folders if we're not treating he file as flat $id = sizeof($folderMap); $folderMap[$node] = $id; $folders[$id] = ['id' => $id, 'name' => $node->getAttribute("text"), 'parent' => $folderMap[$node->parentNode]]; } + // proceed to child nodes, if any $node = $node->hasChildNodes() ? $node->firstChild : ($node->nextSibling ?: $node->parentNode); } } else { + // skip any node which is not an outline element; if the node has descendents they are skipped as well $node = $node->nextSibling ?: $node->parentNode; } }