diff --git a/ChangeLog b/ChangeLog index 19d1106..fd4f3d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Version 1.2.4 (unreleased) +-------------------------- + +* Add migration script to Miniflux 2 +* Add zh_TW and Polish translation +* Use search input type instead of text +* Remove deprecated referrer CSP policy +* Remove doc links from help page +* Use Alpine/Nginx/PHP7 for the Docker image + Version 1.2.3 (June 23 2017) ---------------------------- diff --git a/scripts/migrate-v2.php b/scripts/migrate-v2.php new file mode 100644 index 0000000..d1dc48a --- /dev/null +++ b/scripts/migrate-v2.php @@ -0,0 +1,247 @@ +prepare(' + INSERT INTO users ( + username, + password, + is_admin, + language + ) VALUES (?, ?, ?, ?) RETURNING id'); + $rq->execute(array( + $user['username'], + $user['password'], + $user['is_admin'] == 1 ? 1 : 0, + isset($settings['language']) && $settings['language'] == 'fr_FR' ? 'fr_FR' : 'en_US', + )); + + return $rq->fetchColumn(); +} + +function migrate_integrations(PDO $dst, $dst_user_id, array $user, array $settings) +{ + $rq = $dst->prepare(' + INSERT INTO integrations ( + user_id, + instapaper_enabled, + instapaper_username, + instapaper_password, + pinboard_enabled, + pinboard_tags, + pinboard_token, + wallabag_enabled, + wallabag_url, + wallabag_client_id, + wallabag_client_secret, + wallabag_username, + wallabag_password, + fever_enabled, + fever_username, + fever_password, + fever_token + ) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + '); + + $rq->execute(array( + $dst_user_id, + array_key_exists('instapaper_enabled', $settings) && $settings['instapaper_enabled'] == 1 ? 1 : 0, + isset($settings['instapaper_username']) ? $settings['instapaper_username'] : '', + isset($settings['instapaper_password']) ? $settings['instapaper_password'] : '', + array_key_exists('pinboard_enabled', $settings) && $settings['pinboard_enabled'] == 1 ? 1 : 0, + isset($settings['pinboard_tags']) ? $settings['pinboard_tags'] : '', + isset($settings['pinboard_token']) ? $settings['pinboard_token'] : '', + array_key_exists('wallabag_enabled', $settings) && $settings['wallabag_enabled'] == 1 ? 1 : 0, + isset($settings['wallabag_url']) ? $settings['wallabag_url'] : '', + isset($settings['wallabag_client_id']) ? $settings['wallabag_client_id'] : '', + isset($settings['wallabag_client_secret']) ? $settings['wallabag_client_secret'] : '', + isset($settings['wallabag_username']) ? $settings['wallabag_username'] : '', + isset($settings['wallabag_password']) ? $settings['wallabag_password'] : '', + 1, + $user['username'], + isset($settings['fever_token']) ? $settings['fever_token'] : '', + isset($settings['fever_api_key']) ? $settings['fever_api_key'] : '', + )); +} + +function migrate_categories(PDO $dst, $dst_user_id, $src_user_id) +{ + $rq = $dst->prepare('INSERT INTO categories (user_id, title) VALUES (?, ?) RETURNING id'); + $rq->execute(array($dst_user_id, 'All')); + $default_category_id = $rq->fetchColumn(); + + $categories = array(); + $groups = Model\Group\get_all($src_user_id); + foreach ($groups as $group) { + $rq->execute(array($dst_user_id, trim($group['title']))); + + $category_id = $rq->fetchColumn(); + $categories[$group['id']] = $category_id; + } + + return array($default_category_id, $categories); +} + +function migrate_feeds(PDO $dst, $dst_user_id, $src_user_id, $default_category_id, array $categories) +{ + $mapping = array(); + $feeds = Model\Feed\get_feeds($src_user_id); + $rq = $dst->prepare(' + INSERT INTO feeds ( + user_id, + category_id, + title, + feed_url, + site_url, + crawler + ) + VALUES (?, ?, ?, ?, ?, ?) RETURNING id + '); + + foreach ($feeds as $feed) { + $category_id = $default_category_id; + $group_ids = Model\Group\get_feed_group_ids($feed['id']); + + if (count($group_ids) > 0) { + $category_id = isset($categories[$group_ids[0]]) ? $categories[$group_ids[0]] : $default_category_id; + } + + $rq->execute(array( + $dst_user_id, + $category_id, + $feed['title'], + $feed['feed_url'], + $feed['site_url'], + $feed['download_content'] == 1 ? 1 : 0, + )); + + $feed_id = $rq->fetchColumn(); + $mapping[$feed['id']] = $feed_id; + } + + return $mapping; +} + +function migrate_entries(PDO $dst, $dst_user_id, $src_user_id, array $feeds) +{ + $rq = $dst->prepare(' + INSERT INTO entries ( + user_id, + feed_id, + hash, + published_at, + title, + url, + author, + content, + status, + starred + ) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING id + '); + + $rq2 = $dst->prepare(' + INSERT INTO enclosures ( + user_id, + entry_id, + url, + size, + mime_type + ) + VALUES (?, ?, ?, ?, ?) + '); + + foreach ($feeds as $src_feed_id => $dst_feed_id) { + $items = Database::getInstance('db') + ->table('items') + ->eq('feed_id', $src_feed_id) + ->eq('bookmark', 1) + ->findAll(); + + foreach ($items as $item) { + $rq->execute(array( + $dst_user_id, + $dst_feed_id, + $item['checksum'], + $item['updated'] > 0 ? date('Y-m-d H:i:s', $item['updated']) : date('Y-m-d H:i:s'), + $item['title'], + $item['url'], + $item['author'], + $item['content'], + $item['status'], + $item['bookmark'] == 1 ? 1 : 0, + )); + + $item_id = $rq->fetchColumn(); + + if (! empty($item['enclosure_url']) && ! empty($item['enclosure_type'])) { + $rq2->execute(array( + $dst_user_id, + $item_id, + $item['enclosure_url'], + 0, + $item['enclosure_type'], + )); + } + } + } +} + +echo 'Destination is "'.$options['dsn'].'"'.PHP_EOL; +$dstDB = new PDO($options['dsn']); +$dstDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +$srcDB = PicoDb\Database::getInstance('db')->getConnection(); + +try { + $dstDB->beginTransaction(); + + $rq = $srcDB->prepare('SELECT id, username, password, is_admin, fever_token FROM users'); + $rq->execute(); + $users = $rq->fetchAll(PDO::FETCH_ASSOC); + echo '* '.count($users).' user(s) to migrate'.PHP_EOL; + + foreach ($users as $user) { + $src_user_id = $user['id']; + $settings = Model\Config\get_all($src_user_id); + + echo '* Migrating user: #'.$src_user_id; + $dst_user_id = migrate_user($dstDB, $user, $settings); + echo ' => #'.$dst_user_id.PHP_EOL; + + echo '* Migrating integrations'.PHP_EOL; + migrate_integrations($dstDB, $dst_user_id, $user, $settings); + + echo '* Migrating categories'.PHP_EOL; + list($default_category_id, $categories) = migrate_categories($dstDB, $dst_user_id, $src_user_id); + + echo '* Migrating feeds'.PHP_EOL; + $feeds = migrate_feeds($dstDB, $dst_user_id, $src_user_id, $default_category_id, $categories); + + echo '* Migrating entries'.PHP_EOL; + migrate_entries($dstDB, $dst_user_id, $src_user_id, $feeds); + } + + $dstDB->commit(); +} catch (PDOException $e) { + $dstDB->rollBack(); + echo PHP_EOL.$e->getMessage().PHP_EOL; +}