From 0f7d49c21e23d7cca9bba57c12111338f0d2a2f8 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Mon, 6 May 2019 19:36:39 -0400 Subject: [PATCH] More OPML tests and fixes --- lib/CLI.php | 5 ++-- lib/ImportExport/OPML.php | 23 +++++++++++++-- tests/cases/ImportExport/TestOPML.php | 33 ++++++++++++++++++++++ tests/docroot/Import/OPML/FoldersOnly.opml | 12 ++++++++ 4 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 tests/docroot/Import/OPML/FoldersOnly.opml diff --git a/lib/CLI.php b/lib/CLI.php index 7f22f949..0b1f3b97 100644 --- a/lib/CLI.php +++ b/lib/CLI.php @@ -78,9 +78,8 @@ Commands: user set-pass [] - Changes 's password to . If not password is - specified, a random password will be generated and printed to standard - output. + Changes 's password to . If no password is specified, + a random password will be generated and printed to standard output. The --oldpass= option can be used to supply a user's exiting password if this is required by the authentication driver to change a diff --git a/lib/ImportExport/OPML.php b/lib/ImportExport/OPML.php index 73284135..a45d4e1a 100644 --- a/lib/ImportExport/OPML.php +++ b/lib/ImportExport/OPML.php @@ -151,6 +151,23 @@ class OPML { throw new Exception("invalidSemantics", ['type' => "OPML"]); } $body = $body->item(0); + // function to find the next node in the tree + $next = function(\DOMNode $node, bool $visitChildren = true) use ($body) { + if ($visitChildren && $node->hasChildNodes()) { + return $node->firstChild; + } elseif ($node->nextSibling) { + return $node->nextSibling; + } else { + while (!$node->nextSibling && !$node->isSameNode($body)) { + $node = $node->parentNode; + } + if (!$node->isSameNode($body)) { + return $node->nextSibling; + } else { + return null; + } + } + }; $folders = []; $feeds = []; // add the root folder to a map from folder DOM nodes to folder ID numbers @@ -158,7 +175,7 @@ class OPML { $folderMap[$body] = sizeof($folderMap); // iterate through each node in the body $node = $body->firstChild; - while ($node && !$node->isSameNode($body)) { + while ($node) { if ($node->nodeType == \XML_ELEMENT_NODE && $node->nodeName === "outline") { // process any nodes which are outlines if ($node->getAttribute("type") === "rss") { @@ -187,11 +204,11 @@ class OPML { $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); + $node = $next($node); } } 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; + $node = $next($node, false); } } return [$feeds, $folders]; diff --git a/tests/cases/ImportExport/TestOPML.php b/tests/cases/ImportExport/TestOPML.php index 94d1b057..59ea9c15 100644 --- a/tests/cases/ImportExport/TestOPML.php +++ b/tests/cases/ImportExport/TestOPML.php @@ -166,6 +166,39 @@ OPML_EXPORT_SERIALIZATION; 'tags' => ["whee", "whoo", ""], ], ], []]], + ["FoldersOnly.opml", true, [[], []]], + ["FoldersOnly.opml", false, [[], [1 => + [ + 'id' => 1, + 'name' => "Folder 1", + 'parent' => 0, + ], + [ + 'id' => 2, + 'name' => "Folder 2", + 'parent' => 0, + ], + [ + 'id' => 3, + 'name' => "Also a folder", + 'parent' => 2, + ], + [ + 'id' => 4, + 'name' => "Still a folder", + 'parent' => 2, + ], + [ + 'id' => 5, + 'name' => "Folder 5", + 'parent' => 4, + ], + [ + 'id' => 6, + 'name' => "Folder 6", + 'parent' => 0, + ], + ]]], ]; } } diff --git a/tests/docroot/Import/OPML/FoldersOnly.opml b/tests/docroot/Import/OPML/FoldersOnly.opml new file mode 100644 index 00000000..34b7a69e --- /dev/null +++ b/tests/docroot/Import/OPML/FoldersOnly.opml @@ -0,0 +1,12 @@ + + + + + + + + + + + +