From 349b0144011e25f2b1a727b1d28d49d55b3b2ebb Mon Sep 17 00:00:00 2001 From: VirtualTam Date: Tue, 4 Dec 2018 00:13:42 +0100 Subject: namespacing: \Shaarli\Netscape\NetscapeBookmarkUtils Signed-off-by: VirtualTam --- application/NetscapeBookmarkUtils.php | 220 ------- application/netscape/NetscapeBookmarkUtils.php | 225 +++++++ composer.json | 1 + index.php | 2 +- tests/NetscapeBookmarkUtils/BookmarkExportTest.php | 136 ----- tests/NetscapeBookmarkUtils/BookmarkImportTest.php | 657 --------------------- tests/NetscapeBookmarkUtils/input/empty.htm | 0 .../input/internet_explorer_encoding.htm | 9 - .../input/lowercase_doctype.htm | 8 - .../NetscapeBookmarkUtils/input/netscape_basic.htm | 11 - .../input/netscape_nested.htm | 31 - tests/NetscapeBookmarkUtils/input/no_doctype.htm | 7 - tests/NetscapeBookmarkUtils/input/same_date.htm | 11 - tests/netscape/BookmarkExportTest.php | 137 +++++ tests/netscape/BookmarkImportTest.php | 657 +++++++++++++++++++++ tests/netscape/input/empty.htm | 0 .../netscape/input/internet_explorer_encoding.htm | 9 + tests/netscape/input/lowercase_doctype.htm | 8 + tests/netscape/input/netscape_basic.htm | 11 + tests/netscape/input/netscape_nested.htm | 31 + tests/netscape/input/no_doctype.htm | 7 + tests/netscape/input/same_date.htm | 11 + 22 files changed, 1098 insertions(+), 1091 deletions(-) delete mode 100644 application/NetscapeBookmarkUtils.php create mode 100644 application/netscape/NetscapeBookmarkUtils.php delete mode 100644 tests/NetscapeBookmarkUtils/BookmarkExportTest.php delete mode 100644 tests/NetscapeBookmarkUtils/BookmarkImportTest.php delete mode 100644 tests/NetscapeBookmarkUtils/input/empty.htm delete mode 100644 tests/NetscapeBookmarkUtils/input/internet_explorer_encoding.htm delete mode 100644 tests/NetscapeBookmarkUtils/input/lowercase_doctype.htm delete mode 100644 tests/NetscapeBookmarkUtils/input/netscape_basic.htm delete mode 100644 tests/NetscapeBookmarkUtils/input/netscape_nested.htm delete mode 100644 tests/NetscapeBookmarkUtils/input/no_doctype.htm delete mode 100644 tests/NetscapeBookmarkUtils/input/same_date.htm create mode 100644 tests/netscape/BookmarkExportTest.php create mode 100644 tests/netscape/BookmarkImportTest.php create mode 100644 tests/netscape/input/empty.htm create mode 100644 tests/netscape/input/internet_explorer_encoding.htm create mode 100644 tests/netscape/input/lowercase_doctype.htm create mode 100644 tests/netscape/input/netscape_basic.htm create mode 100644 tests/netscape/input/netscape_nested.htm create mode 100644 tests/netscape/input/no_doctype.htm create mode 100644 tests/netscape/input/same_date.htm diff --git a/application/NetscapeBookmarkUtils.php b/application/NetscapeBookmarkUtils.php deleted file mode 100644 index e0022fe1..00000000 --- a/application/NetscapeBookmarkUtils.php +++ /dev/null @@ -1,220 +0,0 @@ -getTimestamp(); - $link['taglist'] = str_replace(' ', ',', $link['tags']); - - if (startsWith($link['url'], '?') && $prependNoteUrl) { - $link['url'] = $indexUrl . $link['url']; - } - - $bookmarkLinks[] = $link; - } - - return $bookmarkLinks; - } - - /** - * Generates an import status summary - * - * @param string $filename name of the file to import - * @param int $filesize size of the file to import - * @param int $importCount how many links were imported - * @param int $overwriteCount how many links were overwritten - * @param int $skipCount how many links were skipped - * @param int $duration how many seconds did the import take - * - * @return string Summary of the bookmark import status - */ - private static function importStatus( - $filename, - $filesize, - $importCount = 0, - $overwriteCount = 0, - $skipCount = 0, - $duration = 0 - ) { - $status = sprintf(t('File %s (%d bytes) '), $filename, $filesize); - if ($importCount == 0 && $overwriteCount == 0 && $skipCount == 0) { - $status .= t('has an unknown file format. Nothing was imported.'); - } else { - $status .= vsprintf( - t( - 'was successfully processed in %d seconds: ' - .'%d links imported, %d links overwritten, %d links skipped.' - ), - [$duration, $importCount, $overwriteCount, $skipCount] - ); - } - return $status; - } - - /** - * Imports Web bookmarks from an uploaded Netscape bookmark dump - * - * @param array $post Server $_POST parameters - * @param array $files Server $_FILES parameters - * @param LinkDB $linkDb Loaded LinkDB instance - * @param ConfigManager $conf instance - * @param History $history History instance - * - * @return string Summary of the bookmark import status - */ - public static function import($post, $files, $linkDb, $conf, $history) - { - $start = time(); - $filename = $files['filetoupload']['name']; - $filesize = $files['filetoupload']['size']; - $data = file_get_contents($files['filetoupload']['tmp_name']); - - if (preg_match('//i', $data) === 0) { - return self::importStatus($filename, $filesize); - } - - // Overwrite existing links? - $overwrite = ! empty($post['overwrite']); - - // Add tags to all imported links? - if (empty($post['default_tags'])) { - $defaultTags = array(); - } else { - $defaultTags = preg_split( - '/[\s,]+/', - escape($post['default_tags']) - ); - } - - // links are imported as public by default - $defaultPrivacy = 0; - - $parser = new NetscapeBookmarkParser( - true, // nested tag support - $defaultTags, // additional user-specified tags - strval(1 - $defaultPrivacy), // defaultPub = 1 - defaultPrivacy - $conf->get('resource.data_dir') // log path, will be overridden - ); - $logger = new Logger( - $conf->get('resource.data_dir'), - ! $conf->get('dev.debug') ? LogLevel::INFO : LogLevel::DEBUG, - [ - 'prefix' => 'import.', - 'extension' => 'log', - ] - ); - $parser->setLogger($logger); - $bookmarks = $parser->parseString($data); - - $importCount = 0; - $overwriteCount = 0; - $skipCount = 0; - - foreach ($bookmarks as $bkm) { - $private = $defaultPrivacy; - if (empty($post['privacy']) || $post['privacy'] == 'default') { - // use value from the imported file - $private = $bkm['pub'] == '1' ? 0 : 1; - } elseif ($post['privacy'] == 'private') { - // all imported links are private - $private = 1; - } elseif ($post['privacy'] == 'public') { - // all imported links are public - $private = 0; - } - - $newLink = array( - 'title' => $bkm['title'], - 'url' => $bkm['uri'], - 'description' => $bkm['note'], - 'private' => $private, - 'tags' => $bkm['tags'] - ); - - $existingLink = $linkDb->getLinkFromUrl($bkm['uri']); - - if ($existingLink !== false) { - if ($overwrite === false) { - // Do not overwrite an existing link - $skipCount++; - continue; - } - - // Overwrite an existing link, keep its date - $newLink['id'] = $existingLink['id']; - $newLink['created'] = $existingLink['created']; - $newLink['updated'] = new DateTime(); - $newLink['shorturl'] = $existingLink['shorturl']; - $linkDb[$existingLink['id']] = $newLink; - $importCount++; - $overwriteCount++; - continue; - } - - // Add a new link - @ used for UNIX timestamps - $newLinkDate = new DateTime('@'.strval($bkm['time'])); - $newLinkDate->setTimezone(new DateTimeZone(date_default_timezone_get())); - $newLink['created'] = $newLinkDate; - $newLink['id'] = $linkDb->getNextId(); - $newLink['shorturl'] = link_small_hash($newLink['created'], $newLink['id']); - $linkDb[$newLink['id']] = $newLink; - $importCount++; - } - - $linkDb->save($conf->get('resource.page_cache')); - $history->importLinks(); - - $duration = time() - $start; - return self::importStatus( - $filename, - $filesize, - $importCount, - $overwriteCount, - $skipCount, - $duration - ); - } -} diff --git a/application/netscape/NetscapeBookmarkUtils.php b/application/netscape/NetscapeBookmarkUtils.php new file mode 100644 index 00000000..2bf928c2 --- /dev/null +++ b/application/netscape/NetscapeBookmarkUtils.php @@ -0,0 +1,225 @@ +getTimestamp(); + $link['taglist'] = str_replace(' ', ',', $link['tags']); + + if (startsWith($link['url'], '?') && $prependNoteUrl) { + $link['url'] = $indexUrl . $link['url']; + } + + $bookmarkLinks[] = $link; + } + + return $bookmarkLinks; + } + + /** + * Generates an import status summary + * + * @param string $filename name of the file to import + * @param int $filesize size of the file to import + * @param int $importCount how many links were imported + * @param int $overwriteCount how many links were overwritten + * @param int $skipCount how many links were skipped + * @param int $duration how many seconds did the import take + * + * @return string Summary of the bookmark import status + */ + private static function importStatus( + $filename, + $filesize, + $importCount = 0, + $overwriteCount = 0, + $skipCount = 0, + $duration = 0 + ) { + $status = sprintf(t('File %s (%d bytes) '), $filename, $filesize); + if ($importCount == 0 && $overwriteCount == 0 && $skipCount == 0) { + $status .= t('has an unknown file format. Nothing was imported.'); + } else { + $status .= vsprintf( + t( + 'was successfully processed in %d seconds: ' + . '%d links imported, %d links overwritten, %d links skipped.' + ), + [$duration, $importCount, $overwriteCount, $skipCount] + ); + } + return $status; + } + + /** + * Imports Web bookmarks from an uploaded Netscape bookmark dump + * + * @param array $post Server $_POST parameters + * @param array $files Server $_FILES parameters + * @param LinkDB $linkDb Loaded LinkDB instance + * @param ConfigManager $conf instance + * @param History $history History instance + * + * @return string Summary of the bookmark import status + */ + public static function import($post, $files, $linkDb, $conf, $history) + { + $start = time(); + $filename = $files['filetoupload']['name']; + $filesize = $files['filetoupload']['size']; + $data = file_get_contents($files['filetoupload']['tmp_name']); + + if (preg_match('//i', $data) === 0) { + return self::importStatus($filename, $filesize); + } + + // Overwrite existing links? + $overwrite = !empty($post['overwrite']); + + // Add tags to all imported links? + if (empty($post['default_tags'])) { + $defaultTags = array(); + } else { + $defaultTags = preg_split( + '/[\s,]+/', + escape($post['default_tags']) + ); + } + + // links are imported as public by default + $defaultPrivacy = 0; + + $parser = new NetscapeBookmarkParser( + true, // nested tag support + $defaultTags, // additional user-specified tags + strval(1 - $defaultPrivacy), // defaultPub = 1 - defaultPrivacy + $conf->get('resource.data_dir') // log path, will be overridden + ); + $logger = new Logger( + $conf->get('resource.data_dir'), + !$conf->get('dev.debug') ? LogLevel::INFO : LogLevel::DEBUG, + [ + 'prefix' => 'import.', + 'extension' => 'log', + ] + ); + $parser->setLogger($logger); + $bookmarks = $parser->parseString($data); + + $importCount = 0; + $overwriteCount = 0; + $skipCount = 0; + + foreach ($bookmarks as $bkm) { + $private = $defaultPrivacy; + if (empty($post['privacy']) || $post['privacy'] == 'default') { + // use value from the imported file + $private = $bkm['pub'] == '1' ? 0 : 1; + } elseif ($post['privacy'] == 'private') { + // all imported links are private + $private = 1; + } elseif ($post['privacy'] == 'public') { + // all imported links are public + $private = 0; + } + + $newLink = array( + 'title' => $bkm['title'], + 'url' => $bkm['uri'], + 'description' => $bkm['note'], + 'private' => $private, + 'tags' => $bkm['tags'] + ); + + $existingLink = $linkDb->getLinkFromUrl($bkm['uri']); + + if ($existingLink !== false) { + if ($overwrite === false) { + // Do not overwrite an existing link + $skipCount++; + continue; + } + + // Overwrite an existing link, keep its date + $newLink['id'] = $existingLink['id']; + $newLink['created'] = $existingLink['created']; + $newLink['updated'] = new DateTime(); + $newLink['shorturl'] = $existingLink['shorturl']; + $linkDb[$existingLink['id']] = $newLink; + $importCount++; + $overwriteCount++; + continue; + } + + // Add a new link - @ used for UNIX timestamps + $newLinkDate = new DateTime('@' . strval($bkm['time'])); + $newLinkDate->setTimezone(new DateTimeZone(date_default_timezone_get())); + $newLink['created'] = $newLinkDate; + $newLink['id'] = $linkDb->getNextId(); + $newLink['shorturl'] = link_small_hash($newLink['created'], $newLink['id']); + $linkDb[$newLink['id']] = $newLink; + $importCount++; + } + + $linkDb->save($conf->get('resource.page_cache')); + $history->importLinks(); + + $duration = time() - $start; + return self::importStatus( + $filename, + $filesize, + $importCount, + $overwriteCount, + $skipCount, + $duration + ); + } +} diff --git a/composer.json b/composer.json index af763472..c1f47317 100644 --- a/composer.json +++ b/composer.json @@ -45,6 +45,7 @@ "Shaarli\\Exceptions\\": "application/exceptions", "Shaarli\\Feed\\": "application/feed", "Shaarli\\Http\\": "application/http", + "Shaarli\\Netscape\\": "application/netscape", "Shaarli\\Render\\": "application/render", "Shaarli\\Security\\": "application/security", "Shaarli\\Updater\\": "application/updater", diff --git a/index.php b/index.php index 1dec569c..bff8e8ff 100644 --- a/index.php +++ b/index.php @@ -63,7 +63,6 @@ require_once 'application/http/HttpUtils.php'; require_once 'application/http/UrlUtils.php'; require_once 'application/updater/UpdaterUtils.php'; require_once 'application/FileUtils.php'; -require_once 'application/NetscapeBookmarkUtils.php'; require_once 'application/TimeZone.php'; require_once 'application/Utils.php'; require_once 'application/PluginManager.php'; @@ -76,6 +75,7 @@ use \Shaarli\Feed\CachedPage; use \Shaarli\Feed\FeedBuilder; use \Shaarli\History; use \Shaarli\Languages; +use \Shaarli\Netscape\NetscapeBookmarkUtils; use \Shaarli\Render\PageBuilder; use \Shaarli\Render\ThemeUtils; use \Shaarli\Router; diff --git a/tests/NetscapeBookmarkUtils/BookmarkExportTest.php b/tests/NetscapeBookmarkUtils/BookmarkExportTest.php deleted file mode 100644 index adf854c5..00000000 --- a/tests/NetscapeBookmarkUtils/BookmarkExportTest.php +++ /dev/null @@ -1,136 +0,0 @@ -write(self::$testDatastore); - self::$linkDb = new LinkDB(self::$testDatastore, true, false); - } - - /** - * Attempt to export an invalid link selection - * @expectedException Exception - * @expectedExceptionMessageRegExp /Invalid export selection/ - */ - public function testFilterAndFormatInvalid() - { - NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'derp', false, ''); - } - - /** - * Prepare all links for export - */ - public function testFilterAndFormatAll() - { - $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'all', false, ''); - $this->assertEquals(self::$refDb->countLinks(), sizeof($links)); - foreach ($links as $link) { - $date = $link['created']; - $this->assertEquals( - $date->getTimestamp(), - $link['timestamp'] - ); - $this->assertEquals( - str_replace(' ', ',', $link['tags']), - $link['taglist'] - ); - } - } - - /** - * Prepare private links for export - */ - public function testFilterAndFormatPrivate() - { - $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'private', false, ''); - $this->assertEquals(self::$refDb->countPrivateLinks(), sizeof($links)); - foreach ($links as $link) { - $date = $link['created']; - $this->assertEquals( - $date->getTimestamp(), - $link['timestamp'] - ); - $this->assertEquals( - str_replace(' ', ',', $link['tags']), - $link['taglist'] - ); - } - } - - /** - * Prepare public links for export - */ - public function testFilterAndFormatPublic() - { - $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, ''); - $this->assertEquals(self::$refDb->countPublicLinks(), sizeof($links)); - foreach ($links as $link) { - $date = $link['created']; - $this->assertEquals( - $date->getTimestamp(), - $link['timestamp'] - ); - $this->assertEquals( - str_replace(' ', ',', $link['tags']), - $link['taglist'] - ); - } - } - - /** - * Do not prepend notes with the Shaarli index's URL - */ - public function testFilterAndFormatDoNotPrependNoteUrl() - { - $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, ''); - $this->assertEquals( - '?WDWyig', - $links[2]['url'] - ); - } - - /** - * Prepend notes with the Shaarli index's URL - */ - public function testFilterAndFormatPrependNoteUrl() - { - $indexUrl = 'http://localhost:7469/shaarli/'; - $links = NetscapeBookmarkUtils::filterAndFormat( - self::$linkDb, - 'public', - true, - $indexUrl - ); - $this->assertEquals( - $indexUrl . '?WDWyig', - $links[2]['url'] - ); - } -} diff --git a/tests/NetscapeBookmarkUtils/BookmarkImportTest.php b/tests/NetscapeBookmarkUtils/BookmarkImportTest.php deleted file mode 100644 index 98c989bc..00000000 --- a/tests/NetscapeBookmarkUtils/BookmarkImportTest.php +++ /dev/null @@ -1,657 +0,0 @@ - array( - 'name' => $filename, - 'tmp_name' => __DIR__ . '/input/' . $filename, - 'size' => filesize(__DIR__ . '/input/' . $filename) - ) - ); -} - - -/** - * Netscape bookmark import - */ -class BookmarkImportTest extends PHPUnit_Framework_TestCase -{ - /** - * @var string datastore to test write operations - */ - protected static $testDatastore = 'sandbox/datastore.php'; - - /** - * @var string History file path - */ - protected static $historyFilePath = 'sandbox/history.php'; - - /** - * @var LinkDB private LinkDB instance - */ - protected $linkDb = null; - - /** - * @var string Dummy page cache - */ - protected $pagecache = 'tests'; - - /** - * @var ConfigManager instance. - */ - protected $conf; - - /** - * @var History instance. - */ - protected $history; - - /** - * @var string Save the current timezone. - */ - protected static $defaultTimeZone; - - public static function setUpBeforeClass() - { - self::$defaultTimeZone = date_default_timezone_get(); - // Timezone without DST for test consistency - date_default_timezone_set('Africa/Nairobi'); - } - - /** - * Resets test data before each test - */ - protected function setUp() - { - if (file_exists(self::$testDatastore)) { - unlink(self::$testDatastore); - } - // start with an empty datastore - file_put_contents(self::$testDatastore, ''); - $this->linkDb = new LinkDB(self::$testDatastore, true, false); - $this->conf = new ConfigManager('tests/utils/config/configJson'); - $this->conf->set('resource.page_cache', $this->pagecache); - $this->history = new History(self::$historyFilePath); - } - - /** - * Delete history file. - */ - public function tearDown() - { - @unlink(self::$historyFilePath); - } - - public static function tearDownAfterClass() - { - date_default_timezone_set(self::$defaultTimeZone); - } - - /** - * Attempt to import bookmarks from an empty file - */ - public function testImportEmptyData() - { - $files = file2array('empty.htm'); - $this->assertEquals( - 'File empty.htm (0 bytes) has an unknown file format.' - .' Nothing was imported.', - NetscapeBookmarkUtils::import(null, $files, null, $this->conf, $this->history) - ); - $this->assertEquals(0, count($this->linkDb)); - } - - /** - * Attempt to import bookmarks from a file with no Doctype - */ - public function testImportNoDoctype() - { - $files = file2array('no_doctype.htm'); - $this->assertEquals( - 'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.', - NetscapeBookmarkUtils::import(null, $files, null, $this->conf, $this->history) - ); - $this->assertEquals(0, count($this->linkDb)); - } - - /** - * Attempt to import bookmarks from a file with a lowercase Doctype - */ - public function testImportLowecaseDoctype() - { - $files = file2array('lowercase_doctype.htm'); - $this->assertStringMatchesFormat( - 'File lowercase_doctype.htm (386 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import(null, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - } - - - /** - * Ensure IE dumps are supported - */ - public function testImportInternetExplorerEncoding() - { - $files = file2array('internet_explorer_encoding.htm'); - $this->assertStringMatchesFormat( - 'File internet_explorer_encoding.htm (356 bytes) was successfully processed in %d seconds:' - .' 1 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import([], $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(1, count($this->linkDb)); - $this->assertEquals(0, count_private($this->linkDb)); - - $this->assertEquals( - array( - 'id' => 0, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160618_203944'), - 'title' => 'Hg Init a Mercurial tutorial by Joel Spolsky', - 'url' => 'http://hginit.com/', - 'description' => '', - 'private' => 0, - 'tags' => '', - 'shorturl' => 'La37cg', - ), - $this->linkDb->getLinkFromUrl('http://hginit.com/') - ); - } - - /** - * Import bookmarks nested in a folder hierarchy - */ - public function testImportNested() - { - $files = file2array('netscape_nested.htm'); - $this->assertStringMatchesFormat( - 'File netscape_nested.htm (1337 bytes) was successfully processed in %d seconds:' - .' 8 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import([], $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(8, count($this->linkDb)); - $this->assertEquals(2, count_private($this->linkDb)); - - $this->assertEquals( - array( - 'id' => 0, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235541'), - 'title' => 'Nested 1', - 'url' => 'http://nest.ed/1', - 'description' => '', - 'private' => 0, - 'tags' => 'tag1 tag2', - 'shorturl' => 'KyDNKA', - ), - $this->linkDb->getLinkFromUrl('http://nest.ed/1') - ); - $this->assertEquals( - array( - 'id' => 1, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235542'), - 'title' => 'Nested 1-1', - 'url' => 'http://nest.ed/1-1', - 'description' => '', - 'private' => 0, - 'tags' => 'folder1 tag1 tag2', - 'shorturl' => 'T2LnXg', - ), - $this->linkDb->getLinkFromUrl('http://nest.ed/1-1') - ); - $this->assertEquals( - array( - 'id' => 2, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235547'), - 'title' => 'Nested 1-2', - 'url' => 'http://nest.ed/1-2', - 'description' => '', - 'private' => 0, - 'tags' => 'folder1 tag3 tag4', - 'shorturl' => '46SZxA', - ), - $this->linkDb->getLinkFromUrl('http://nest.ed/1-2') - ); - $this->assertEquals( - array( - 'id' => 3, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160202_202222'), - 'title' => 'Nested 2-1', - 'url' => 'http://nest.ed/2-1', - 'description' => 'First link of the second section', - 'private' => 1, - 'tags' => 'folder2', - 'shorturl' => '4UHOSw', - ), - $this->linkDb->getLinkFromUrl('http://nest.ed/2-1') - ); - $this->assertEquals( - array( - 'id' => 4, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160119_230227'), - 'title' => 'Nested 2-2', - 'url' => 'http://nest.ed/2-2', - 'description' => 'Second link of the second section', - 'private' => 1, - 'tags' => 'folder2', - 'shorturl' => 'yfzwbw', - ), - $this->linkDb->getLinkFromUrl('http://nest.ed/2-2') - ); - $this->assertEquals( - array( - 'id' => 5, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160202_202222'), - 'title' => 'Nested 3-1', - 'url' => 'http://nest.ed/3-1', - 'description' => '', - 'private' => 0, - 'tags' => 'folder3 folder3-1 tag3', - 'shorturl' => 'UwxIUQ', - ), - $this->linkDb->getLinkFromUrl('http://nest.ed/3-1') - ); - $this->assertEquals( - array( - 'id' => 6, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160119_230227'), - 'title' => 'Nested 3-2', - 'url' => 'http://nest.ed/3-2', - 'description' => '', - 'private' => 0, - 'tags' => 'folder3 folder3-1', - 'shorturl' => 'p8dyZg', - ), - $this->linkDb->getLinkFromUrl('http://nest.ed/3-2') - ); - $this->assertEquals( - array( - 'id' => 7, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160229_111541'), - 'title' => 'Nested 2', - 'url' => 'http://nest.ed/2', - 'description' => '', - 'private' => 0, - 'tags' => 'tag4', - 'shorturl' => 'Gt3Uug', - ), - $this->linkDb->getLinkFromUrl('http://nest.ed/2') - ); - } - - /** - * Import bookmarks with the default privacy setting (reuse from file) - * - * The $_POST array is not set. - */ - public function testImportDefaultPrivacyNoPost() - { - $files = file2array('netscape_basic.htm'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import([], $files, $this->linkDb, $this->conf, $this->history) - ); - - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(1, count_private($this->linkDb)); - - $this->assertEquals( - array( - 'id' => 0, - // Old link - UTC+4 (note that TZ in the import file is ignored). - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20001010_135536'), - 'title' => 'Secret stuff', - 'url' => 'https://private.tld', - 'description' => "Super-secret stuff you're not supposed to know about", - 'private' => 1, - 'tags' => 'private secret', - 'shorturl' => 'EokDtA', - ), - $this->linkDb->getLinkFromUrl('https://private.tld') - ); - $this->assertEquals( - array( - 'id' => 1, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235548'), - 'title' => 'Public stuff', - 'url' => 'http://public.tld', - 'description' => '', - 'private' => 0, - 'tags' => 'public hello world', - 'shorturl' => 'Er9ddA', - ), - $this->linkDb->getLinkFromUrl('http://public.tld') - ); - } - - /** - * Import bookmarks with the default privacy setting (reuse from file) - */ - public function testImportKeepPrivacy() - { - $post = array('privacy' => 'default'); - $files = file2array('netscape_basic.htm'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(1, count_private($this->linkDb)); - - $this->assertEquals( - array( - 'id' => 0, - // Note that TZ in the import file is ignored. - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20001010_135536'), - 'title' => 'Secret stuff', - 'url' => 'https://private.tld', - 'description' => "Super-secret stuff you're not supposed to know about", - 'private' => 1, - 'tags' => 'private secret', - 'shorturl' => 'EokDtA', - ), - $this->linkDb->getLinkFromUrl('https://private.tld') - ); - $this->assertEquals( - array( - 'id' => 1, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235548'), - 'title' => 'Public stuff', - 'url' => 'http://public.tld', - 'description' => '', - 'private' => 0, - 'tags' => 'public hello world', - 'shorturl' => 'Er9ddA', - ), - $this->linkDb->getLinkFromUrl('http://public.tld') - ); - } - - /** - * Import links as public - */ - public function testImportAsPublic() - { - $post = array('privacy' => 'public'); - $files = file2array('netscape_basic.htm'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(0, count_private($this->linkDb)); - $this->assertEquals( - 0, - $this->linkDb[0]['private'] - ); - $this->assertEquals( - 0, - $this->linkDb[1]['private'] - ); - } - - /** - * Import links as private - */ - public function testImportAsPrivate() - { - $post = array('privacy' => 'private'); - $files = file2array('netscape_basic.htm'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(2, count_private($this->linkDb)); - $this->assertEquals( - 1, - $this->linkDb['0']['private'] - ); - $this->assertEquals( - 1, - $this->linkDb['1']['private'] - ); - } - - /** - * Overwrite private links so they become public - */ - public function testOverwriteAsPublic() - { - $files = file2array('netscape_basic.htm'); - - // import links as private - $post = array('privacy' => 'private'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(2, count_private($this->linkDb)); - $this->assertEquals( - 1, - $this->linkDb[0]['private'] - ); - $this->assertEquals( - 1, - $this->linkDb[1]['private'] - ); - // re-import as public, enable overwriting - $post = array( - 'privacy' => 'public', - 'overwrite' => 'true' - ); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 2 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(0, count_private($this->linkDb)); - $this->assertEquals( - 0, - $this->linkDb[0]['private'] - ); - $this->assertEquals( - 0, - $this->linkDb[1]['private'] - ); - } - - /** - * Overwrite public links so they become private - */ - public function testOverwriteAsPrivate() - { - $files = file2array('netscape_basic.htm'); - - // import links as public - $post = array('privacy' => 'public'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(0, count_private($this->linkDb)); - $this->assertEquals( - 0, - $this->linkDb['0']['private'] - ); - $this->assertEquals( - 0, - $this->linkDb['1']['private'] - ); - - // re-import as private, enable overwriting - $post = array( - 'privacy' => 'private', - 'overwrite' => 'true' - ); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 2 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(2, count_private($this->linkDb)); - $this->assertEquals( - 1, - $this->linkDb['0']['private'] - ); - $this->assertEquals( - 1, - $this->linkDb['1']['private'] - ); - } - - /** - * Attept to import the same links twice without enabling overwriting - */ - public function testSkipOverwrite() - { - $post = array('privacy' => 'public'); - $files = file2array('netscape_basic.htm'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(0, count_private($this->linkDb)); - - // re-import as private, DO NOT enable overwriting - $post = array('privacy' => 'private'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 0 links imported, 0 links overwritten, 2 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(0, count_private($this->linkDb)); - } - - /** - * Add user-specified tags to all imported bookmarks - */ - public function testSetDefaultTags() - { - $post = array( - 'privacy' => 'public', - 'default_tags' => 'tag1,tag2 tag3' - ); - $files = file2array('netscape_basic.htm'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(0, count_private($this->linkDb)); - $this->assertEquals( - 'tag1 tag2 tag3 private secret', - $this->linkDb['0']['tags'] - ); - $this->assertEquals( - 'tag1 tag2 tag3 public hello world', - $this->linkDb['1']['tags'] - ); - } - - /** - * The user-specified tags contain characters to be escaped - */ - public function testSanitizeDefaultTags() - { - $post = array( - 'privacy' => 'public', - 'default_tags' => 'tag1&,tag2 "tag3"' - ); - $files = file2array('netscape_basic.htm'); - $this->assertStringMatchesFormat( - 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' - .' 2 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(2, count($this->linkDb)); - $this->assertEquals(0, count_private($this->linkDb)); - $this->assertEquals( - 'tag1& tag2 "tag3" private secret', - $this->linkDb['0']['tags'] - ); - $this->assertEquals( - 'tag1& tag2 "tag3" public hello world', - $this->linkDb['1']['tags'] - ); - } - - /** - * Ensure each imported bookmark has a unique id - * - * See https://github.com/shaarli/Shaarli/issues/351 - */ - public function testImportSameDate() - { - $files = file2array('same_date.htm'); - $this->assertStringMatchesFormat( - 'File same_date.htm (453 bytes) was successfully processed in %d seconds:' - .' 3 links imported, 0 links overwritten, 0 links skipped.', - NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf, $this->history) - ); - $this->assertEquals(3, count($this->linkDb)); - $this->assertEquals(0, count_private($this->linkDb)); - $this->assertEquals( - 0, - $this->linkDb[0]['id'] - ); - $this->assertEquals( - 1, - $this->linkDb[1]['id'] - ); - $this->assertEquals( - 2, - $this->linkDb[2]['id'] - ); - } - - public function testImportCreateUpdateHistory() - { - $post = [ - 'privacy' => 'public', - 'overwrite' => 'true', - ]; - $files = file2array('netscape_basic.htm'); - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history); - $history = $this->history->getHistory(); - $this->assertEquals(1, count($history)); - $this->assertEquals(History::IMPORT, $history[0]['event']); - $this->assertTrue(new DateTime('-5 seconds') < $history[0]['datetime']); - - // re-import as private, enable overwriting - NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history); - $history = $this->history->getHistory(); - $this->assertEquals(2, count($history)); - $this->assertEquals(History::IMPORT, $history[0]['event']); - $this->assertTrue(new DateTime('-5 seconds') < $history[0]['datetime']); - $this->assertEquals(History::IMPORT, $history[1]['event']); - $this->assertTrue(new DateTime('-5 seconds') < $history[1]['datetime']); - } -} diff --git a/tests/NetscapeBookmarkUtils/input/empty.htm b/tests/NetscapeBookmarkUtils/input/empty.htm deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/NetscapeBookmarkUtils/input/internet_explorer_encoding.htm b/tests/NetscapeBookmarkUtils/input/internet_explorer_encoding.htm deleted file mode 100644 index 18703cf6..00000000 --- a/tests/NetscapeBookmarkUtils/input/internet_explorer_encoding.htm +++ /dev/null @@ -1,9 +0,0 @@ - - -Bookmarks -

Bookmarks

-

-

Hg Init a Mercurial tutorial by Joel Spolsky -

diff --git a/tests/NetscapeBookmarkUtils/input/lowercase_doctype.htm b/tests/NetscapeBookmarkUtils/input/lowercase_doctype.htm deleted file mode 100644 index 8911ad19..00000000 --- a/tests/NetscapeBookmarkUtils/input/lowercase_doctype.htm +++ /dev/null @@ -1,8 +0,0 @@ - -Bookmarks -

Bookmarks

-

-

Secret stuff -
Super-secret stuff you're not supposed to know about -
Public stuff -

diff --git a/tests/NetscapeBookmarkUtils/input/netscape_basic.htm b/tests/NetscapeBookmarkUtils/input/netscape_basic.htm deleted file mode 100644 index affe0cf8..00000000 --- a/tests/NetscapeBookmarkUtils/input/netscape_basic.htm +++ /dev/null @@ -1,11 +0,0 @@ - - -Bookmarks -

Bookmarks

-

-

Secret stuff -
Super-secret stuff you're not supposed to know about -
Public stuff -

diff --git a/tests/NetscapeBookmarkUtils/input/netscape_nested.htm b/tests/NetscapeBookmarkUtils/input/netscape_nested.htm deleted file mode 100644 index b486fe18..00000000 --- a/tests/NetscapeBookmarkUtils/input/netscape_nested.htm +++ /dev/null @@ -1,31 +0,0 @@ - - -Bookmarks -

Bookmarks

-

-

Nested 1 -

Folder1

-

-

Nested 1-1 -
Nested 1-2 -

-

Folder2

-
This second folder contains wonderful links! -

-

Nested 2-1 -
First link of the second section -
Nested 2-2 -
Second link of the second section -

-

Folder3

-

-

Folder3-1

-

-

Nested 3-1 -
Nested 3-2 -

-

-

Nested 2 -

diff --git a/tests/NetscapeBookmarkUtils/input/no_doctype.htm b/tests/NetscapeBookmarkUtils/input/no_doctype.htm deleted file mode 100644 index 766d398b..00000000 --- a/tests/NetscapeBookmarkUtils/input/no_doctype.htm +++ /dev/null @@ -1,7 +0,0 @@ -Bookmarks -

Bookmarks

-

-

Secret stuff -
Super-secret stuff you're not supposed to know about -
Public stuff -

diff --git a/tests/NetscapeBookmarkUtils/input/same_date.htm b/tests/NetscapeBookmarkUtils/input/same_date.htm deleted file mode 100644 index 9d58a582..00000000 --- a/tests/NetscapeBookmarkUtils/input/same_date.htm +++ /dev/null @@ -1,11 +0,0 @@ - - -Bookmarks -

Bookmarks

-

-

Today's first link -
Today's second link -
Today's third link -

diff --git a/tests/netscape/BookmarkExportTest.php b/tests/netscape/BookmarkExportTest.php new file mode 100644 index 00000000..6de9876d --- /dev/null +++ b/tests/netscape/BookmarkExportTest.php @@ -0,0 +1,137 @@ +write(self::$testDatastore); + self::$linkDb = new LinkDB(self::$testDatastore, true, false); + } + + /** + * Attempt to export an invalid link selection + * @expectedException Exception + * @expectedExceptionMessageRegExp /Invalid export selection/ + */ + public function testFilterAndFormatInvalid() + { + NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'derp', false, ''); + } + + /** + * Prepare all links for export + */ + public function testFilterAndFormatAll() + { + $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'all', false, ''); + $this->assertEquals(self::$refDb->countLinks(), sizeof($links)); + foreach ($links as $link) { + $date = $link['created']; + $this->assertEquals( + $date->getTimestamp(), + $link['timestamp'] + ); + $this->assertEquals( + str_replace(' ', ',', $link['tags']), + $link['taglist'] + ); + } + } + + /** + * Prepare private links for export + */ + public function testFilterAndFormatPrivate() + { + $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'private', false, ''); + $this->assertEquals(self::$refDb->countPrivateLinks(), sizeof($links)); + foreach ($links as $link) { + $date = $link['created']; + $this->assertEquals( + $date->getTimestamp(), + $link['timestamp'] + ); + $this->assertEquals( + str_replace(' ', ',', $link['tags']), + $link['taglist'] + ); + } + } + + /** + * Prepare public links for export + */ + public function testFilterAndFormatPublic() + { + $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, ''); + $this->assertEquals(self::$refDb->countPublicLinks(), sizeof($links)); + foreach ($links as $link) { + $date = $link['created']; + $this->assertEquals( + $date->getTimestamp(), + $link['timestamp'] + ); + $this->assertEquals( + str_replace(' ', ',', $link['tags']), + $link['taglist'] + ); + } + } + + /** + * Do not prepend notes with the Shaarli index's URL + */ + public function testFilterAndFormatDoNotPrependNoteUrl() + { + $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, ''); + $this->assertEquals( + '?WDWyig', + $links[2]['url'] + ); + } + + /** + * Prepend notes with the Shaarli index's URL + */ + public function testFilterAndFormatPrependNoteUrl() + { + $indexUrl = 'http://localhost:7469/shaarli/'; + $links = NetscapeBookmarkUtils::filterAndFormat( + self::$linkDb, + 'public', + true, + $indexUrl + ); + $this->assertEquals( + $indexUrl . '?WDWyig', + $links[2]['url'] + ); + } +} diff --git a/tests/netscape/BookmarkImportTest.php b/tests/netscape/BookmarkImportTest.php new file mode 100644 index 00000000..ccafc161 --- /dev/null +++ b/tests/netscape/BookmarkImportTest.php @@ -0,0 +1,657 @@ + array( + 'name' => $filename, + 'tmp_name' => __DIR__ . '/input/' . $filename, + 'size' => filesize(__DIR__ . '/input/' . $filename) + ) + ); +} + + +/** + * Netscape bookmark import + */ +class BookmarkImportTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var string datastore to test write operations + */ + protected static $testDatastore = 'sandbox/datastore.php'; + + /** + * @var string History file path + */ + protected static $historyFilePath = 'sandbox/history.php'; + + /** + * @var LinkDB private LinkDB instance + */ + protected $linkDb = null; + + /** + * @var string Dummy page cache + */ + protected $pagecache = 'tests'; + + /** + * @var ConfigManager instance. + */ + protected $conf; + + /** + * @var History instance. + */ + protected $history; + + /** + * @var string Save the current timezone. + */ + protected static $defaultTimeZone; + + public static function setUpBeforeClass() + { + self::$defaultTimeZone = date_default_timezone_get(); + // Timezone without DST for test consistency + date_default_timezone_set('Africa/Nairobi'); + } + + /** + * Resets test data before each test + */ + protected function setUp() + { + if (file_exists(self::$testDatastore)) { + unlink(self::$testDatastore); + } + // start with an empty datastore + file_put_contents(self::$testDatastore, ''); + $this->linkDb = new LinkDB(self::$testDatastore, true, false); + $this->conf = new ConfigManager('tests/utils/config/configJson'); + $this->conf->set('resource.page_cache', $this->pagecache); + $this->history = new History(self::$historyFilePath); + } + + /** + * Delete history file. + */ + public function tearDown() + { + @unlink(self::$historyFilePath); + } + + public static function tearDownAfterClass() + { + date_default_timezone_set(self::$defaultTimeZone); + } + + /** + * Attempt to import bookmarks from an empty file + */ + public function testImportEmptyData() + { + $files = file2array('empty.htm'); + $this->assertEquals( + 'File empty.htm (0 bytes) has an unknown file format.' + .' Nothing was imported.', + NetscapeBookmarkUtils::import(null, $files, null, $this->conf, $this->history) + ); + $this->assertEquals(0, count($this->linkDb)); + } + + /** + * Attempt to import bookmarks from a file with no Doctype + */ + public function testImportNoDoctype() + { + $files = file2array('no_doctype.htm'); + $this->assertEquals( + 'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.', + NetscapeBookmarkUtils::import(null, $files, null, $this->conf, $this->history) + ); + $this->assertEquals(0, count($this->linkDb)); + } + + /** + * Attempt to import bookmarks from a file with a lowercase Doctype + */ + public function testImportLowecaseDoctype() + { + $files = file2array('lowercase_doctype.htm'); + $this->assertStringMatchesFormat( + 'File lowercase_doctype.htm (386 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import(null, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + } + + + /** + * Ensure IE dumps are supported + */ + public function testImportInternetExplorerEncoding() + { + $files = file2array('internet_explorer_encoding.htm'); + $this->assertStringMatchesFormat( + 'File internet_explorer_encoding.htm (356 bytes) was successfully processed in %d seconds:' + .' 1 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import([], $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(1, count($this->linkDb)); + $this->assertEquals(0, count_private($this->linkDb)); + + $this->assertEquals( + array( + 'id' => 0, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160618_203944'), + 'title' => 'Hg Init a Mercurial tutorial by Joel Spolsky', + 'url' => 'http://hginit.com/', + 'description' => '', + 'private' => 0, + 'tags' => '', + 'shorturl' => 'La37cg', + ), + $this->linkDb->getLinkFromUrl('http://hginit.com/') + ); + } + + /** + * Import bookmarks nested in a folder hierarchy + */ + public function testImportNested() + { + $files = file2array('netscape_nested.htm'); + $this->assertStringMatchesFormat( + 'File netscape_nested.htm (1337 bytes) was successfully processed in %d seconds:' + .' 8 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import([], $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(8, count($this->linkDb)); + $this->assertEquals(2, count_private($this->linkDb)); + + $this->assertEquals( + array( + 'id' => 0, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235541'), + 'title' => 'Nested 1', + 'url' => 'http://nest.ed/1', + 'description' => '', + 'private' => 0, + 'tags' => 'tag1 tag2', + 'shorturl' => 'KyDNKA', + ), + $this->linkDb->getLinkFromUrl('http://nest.ed/1') + ); + $this->assertEquals( + array( + 'id' => 1, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235542'), + 'title' => 'Nested 1-1', + 'url' => 'http://nest.ed/1-1', + 'description' => '', + 'private' => 0, + 'tags' => 'folder1 tag1 tag2', + 'shorturl' => 'T2LnXg', + ), + $this->linkDb->getLinkFromUrl('http://nest.ed/1-1') + ); + $this->assertEquals( + array( + 'id' => 2, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235547'), + 'title' => 'Nested 1-2', + 'url' => 'http://nest.ed/1-2', + 'description' => '', + 'private' => 0, + 'tags' => 'folder1 tag3 tag4', + 'shorturl' => '46SZxA', + ), + $this->linkDb->getLinkFromUrl('http://nest.ed/1-2') + ); + $this->assertEquals( + array( + 'id' => 3, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160202_202222'), + 'title' => 'Nested 2-1', + 'url' => 'http://nest.ed/2-1', + 'description' => 'First link of the second section', + 'private' => 1, + 'tags' => 'folder2', + 'shorturl' => '4UHOSw', + ), + $this->linkDb->getLinkFromUrl('http://nest.ed/2-1') + ); + $this->assertEquals( + array( + 'id' => 4, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160119_230227'), + 'title' => 'Nested 2-2', + 'url' => 'http://nest.ed/2-2', + 'description' => 'Second link of the second section', + 'private' => 1, + 'tags' => 'folder2', + 'shorturl' => 'yfzwbw', + ), + $this->linkDb->getLinkFromUrl('http://nest.ed/2-2') + ); + $this->assertEquals( + array( + 'id' => 5, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160202_202222'), + 'title' => 'Nested 3-1', + 'url' => 'http://nest.ed/3-1', + 'description' => '', + 'private' => 0, + 'tags' => 'folder3 folder3-1 tag3', + 'shorturl' => 'UwxIUQ', + ), + $this->linkDb->getLinkFromUrl('http://nest.ed/3-1') + ); + $this->assertEquals( + array( + 'id' => 6, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160119_230227'), + 'title' => 'Nested 3-2', + 'url' => 'http://nest.ed/3-2', + 'description' => '', + 'private' => 0, + 'tags' => 'folder3 folder3-1', + 'shorturl' => 'p8dyZg', + ), + $this->linkDb->getLinkFromUrl('http://nest.ed/3-2') + ); + $this->assertEquals( + array( + 'id' => 7, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160229_111541'), + 'title' => 'Nested 2', + 'url' => 'http://nest.ed/2', + 'description' => '', + 'private' => 0, + 'tags' => 'tag4', + 'shorturl' => 'Gt3Uug', + ), + $this->linkDb->getLinkFromUrl('http://nest.ed/2') + ); + } + + /** + * Import bookmarks with the default privacy setting (reuse from file) + * + * The $_POST array is not set. + */ + public function testImportDefaultPrivacyNoPost() + { + $files = file2array('netscape_basic.htm'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import([], $files, $this->linkDb, $this->conf, $this->history) + ); + + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(1, count_private($this->linkDb)); + + $this->assertEquals( + array( + 'id' => 0, + // Old link - UTC+4 (note that TZ in the import file is ignored). + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20001010_135536'), + 'title' => 'Secret stuff', + 'url' => 'https://private.tld', + 'description' => "Super-secret stuff you're not supposed to know about", + 'private' => 1, + 'tags' => 'private secret', + 'shorturl' => 'EokDtA', + ), + $this->linkDb->getLinkFromUrl('https://private.tld') + ); + $this->assertEquals( + array( + 'id' => 1, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235548'), + 'title' => 'Public stuff', + 'url' => 'http://public.tld', + 'description' => '', + 'private' => 0, + 'tags' => 'public hello world', + 'shorturl' => 'Er9ddA', + ), + $this->linkDb->getLinkFromUrl('http://public.tld') + ); + } + + /** + * Import bookmarks with the default privacy setting (reuse from file) + */ + public function testImportKeepPrivacy() + { + $post = array('privacy' => 'default'); + $files = file2array('netscape_basic.htm'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(1, count_private($this->linkDb)); + + $this->assertEquals( + array( + 'id' => 0, + // Note that TZ in the import file is ignored. + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20001010_135536'), + 'title' => 'Secret stuff', + 'url' => 'https://private.tld', + 'description' => "Super-secret stuff you're not supposed to know about", + 'private' => 1, + 'tags' => 'private secret', + 'shorturl' => 'EokDtA', + ), + $this->linkDb->getLinkFromUrl('https://private.tld') + ); + $this->assertEquals( + array( + 'id' => 1, + 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20160225_235548'), + 'title' => 'Public stuff', + 'url' => 'http://public.tld', + 'description' => '', + 'private' => 0, + 'tags' => 'public hello world', + 'shorturl' => 'Er9ddA', + ), + $this->linkDb->getLinkFromUrl('http://public.tld') + ); + } + + /** + * Import links as public + */ + public function testImportAsPublic() + { + $post = array('privacy' => 'public'); + $files = file2array('netscape_basic.htm'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(0, count_private($this->linkDb)); + $this->assertEquals( + 0, + $this->linkDb[0]['private'] + ); + $this->assertEquals( + 0, + $this->linkDb[1]['private'] + ); + } + + /** + * Import links as private + */ + public function testImportAsPrivate() + { + $post = array('privacy' => 'private'); + $files = file2array('netscape_basic.htm'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(2, count_private($this->linkDb)); + $this->assertEquals( + 1, + $this->linkDb['0']['private'] + ); + $this->assertEquals( + 1, + $this->linkDb['1']['private'] + ); + } + + /** + * Overwrite private links so they become public + */ + public function testOverwriteAsPublic() + { + $files = file2array('netscape_basic.htm'); + + // import links as private + $post = array('privacy' => 'private'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(2, count_private($this->linkDb)); + $this->assertEquals( + 1, + $this->linkDb[0]['private'] + ); + $this->assertEquals( + 1, + $this->linkDb[1]['private'] + ); + // re-import as public, enable overwriting + $post = array( + 'privacy' => 'public', + 'overwrite' => 'true' + ); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 2 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(0, count_private($this->linkDb)); + $this->assertEquals( + 0, + $this->linkDb[0]['private'] + ); + $this->assertEquals( + 0, + $this->linkDb[1]['private'] + ); + } + + /** + * Overwrite public links so they become private + */ + public function testOverwriteAsPrivate() + { + $files = file2array('netscape_basic.htm'); + + // import links as public + $post = array('privacy' => 'public'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(0, count_private($this->linkDb)); + $this->assertEquals( + 0, + $this->linkDb['0']['private'] + ); + $this->assertEquals( + 0, + $this->linkDb['1']['private'] + ); + + // re-import as private, enable overwriting + $post = array( + 'privacy' => 'private', + 'overwrite' => 'true' + ); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 2 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(2, count_private($this->linkDb)); + $this->assertEquals( + 1, + $this->linkDb['0']['private'] + ); + $this->assertEquals( + 1, + $this->linkDb['1']['private'] + ); + } + + /** + * Attept to import the same links twice without enabling overwriting + */ + public function testSkipOverwrite() + { + $post = array('privacy' => 'public'); + $files = file2array('netscape_basic.htm'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(0, count_private($this->linkDb)); + + // re-import as private, DO NOT enable overwriting + $post = array('privacy' => 'private'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 0 links imported, 0 links overwritten, 2 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(0, count_private($this->linkDb)); + } + + /** + * Add user-specified tags to all imported bookmarks + */ + public function testSetDefaultTags() + { + $post = array( + 'privacy' => 'public', + 'default_tags' => 'tag1,tag2 tag3' + ); + $files = file2array('netscape_basic.htm'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(0, count_private($this->linkDb)); + $this->assertEquals( + 'tag1 tag2 tag3 private secret', + $this->linkDb['0']['tags'] + ); + $this->assertEquals( + 'tag1 tag2 tag3 public hello world', + $this->linkDb['1']['tags'] + ); + } + + /** + * The user-specified tags contain characters to be escaped + */ + public function testSanitizeDefaultTags() + { + $post = array( + 'privacy' => 'public', + 'default_tags' => 'tag1&,tag2 "tag3"' + ); + $files = file2array('netscape_basic.htm'); + $this->assertStringMatchesFormat( + 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' + .' 2 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(2, count($this->linkDb)); + $this->assertEquals(0, count_private($this->linkDb)); + $this->assertEquals( + 'tag1& tag2 "tag3" private secret', + $this->linkDb['0']['tags'] + ); + $this->assertEquals( + 'tag1& tag2 "tag3" public hello world', + $this->linkDb['1']['tags'] + ); + } + + /** + * Ensure each imported bookmark has a unique id + * + * See https://github.com/shaarli/Shaarli/issues/351 + */ + public function testImportSameDate() + { + $files = file2array('same_date.htm'); + $this->assertStringMatchesFormat( + 'File same_date.htm (453 bytes) was successfully processed in %d seconds:' + .' 3 links imported, 0 links overwritten, 0 links skipped.', + NetscapeBookmarkUtils::import(array(), $files, $this->linkDb, $this->conf, $this->history) + ); + $this->assertEquals(3, count($this->linkDb)); + $this->assertEquals(0, count_private($this->linkDb)); + $this->assertEquals( + 0, + $this->linkDb[0]['id'] + ); + $this->assertEquals( + 1, + $this->linkDb[1]['id'] + ); + $this->assertEquals( + 2, + $this->linkDb[2]['id'] + ); + } + + public function testImportCreateUpdateHistory() + { + $post = [ + 'privacy' => 'public', + 'overwrite' => 'true', + ]; + $files = file2array('netscape_basic.htm'); + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history); + $history = $this->history->getHistory(); + $this->assertEquals(1, count($history)); + $this->assertEquals(History::IMPORT, $history[0]['event']); + $this->assertTrue(new DateTime('-5 seconds') < $history[0]['datetime']); + + // re-import as private, enable overwriting + NetscapeBookmarkUtils::import($post, $files, $this->linkDb, $this->conf, $this->history); + $history = $this->history->getHistory(); + $this->assertEquals(2, count($history)); + $this->assertEquals(History::IMPORT, $history[0]['event']); + $this->assertTrue(new DateTime('-5 seconds') < $history[0]['datetime']); + $this->assertEquals(History::IMPORT, $history[1]['event']); + $this->assertTrue(new DateTime('-5 seconds') < $history[1]['datetime']); + } +} diff --git a/tests/netscape/input/empty.htm b/tests/netscape/input/empty.htm new file mode 100644 index 00000000..e69de29b diff --git a/tests/netscape/input/internet_explorer_encoding.htm b/tests/netscape/input/internet_explorer_encoding.htm new file mode 100644 index 00000000..18703cf6 --- /dev/null +++ b/tests/netscape/input/internet_explorer_encoding.htm @@ -0,0 +1,9 @@ + + +Bookmarks +

Bookmarks

+

+

Hg Init a Mercurial tutorial by Joel Spolsky +

diff --git a/tests/netscape/input/lowercase_doctype.htm b/tests/netscape/input/lowercase_doctype.htm new file mode 100644 index 00000000..8911ad19 --- /dev/null +++ b/tests/netscape/input/lowercase_doctype.htm @@ -0,0 +1,8 @@ + +Bookmarks +

Bookmarks

+

+

Secret stuff +
Super-secret stuff you're not supposed to know about +
Public stuff +

diff --git a/tests/netscape/input/netscape_basic.htm b/tests/netscape/input/netscape_basic.htm new file mode 100644 index 00000000..affe0cf8 --- /dev/null +++ b/tests/netscape/input/netscape_basic.htm @@ -0,0 +1,11 @@ + + +Bookmarks +

Bookmarks

+

+

Secret stuff +
Super-secret stuff you're not supposed to know about +
Public stuff +

diff --git a/tests/netscape/input/netscape_nested.htm b/tests/netscape/input/netscape_nested.htm new file mode 100644 index 00000000..b486fe18 --- /dev/null +++ b/tests/netscape/input/netscape_nested.htm @@ -0,0 +1,31 @@ + + +Bookmarks +

Bookmarks

+

+

Nested 1 +

Folder1

+

+

Nested 1-1 +
Nested 1-2 +

+

Folder2

+
This second folder contains wonderful links! +

+

Nested 2-1 +
First link of the second section +
Nested 2-2 +
Second link of the second section +

+

Folder3

+

+

Folder3-1

+

+

Nested 3-1 +
Nested 3-2 +

+

+

Nested 2 +

diff --git a/tests/netscape/input/no_doctype.htm b/tests/netscape/input/no_doctype.htm new file mode 100644 index 00000000..766d398b --- /dev/null +++ b/tests/netscape/input/no_doctype.htm @@ -0,0 +1,7 @@ +Bookmarks +

Bookmarks

+

+

Secret stuff +
Super-secret stuff you're not supposed to know about +
Public stuff +

diff --git a/tests/netscape/input/same_date.htm b/tests/netscape/input/same_date.htm new file mode 100644 index 00000000..9d58a582 --- /dev/null +++ b/tests/netscape/input/same_date.htm @@ -0,0 +1,11 @@ + + +Bookmarks +

Bookmarks

+

+

Today's first link +
Today's second link +
Today's third link +

-- cgit v1.2.3