miniflux-legacy/scripts/migrate-v2.php

248 lines
7.6 KiB
PHP

<?php
require_once __DIR__.'/../app/common.php';
use Miniflux\Model;
use PicoDb\Database;
if (php_sapi_name() !== 'cli') {
die('This script can run only from the command line.'.PHP_EOL);
}
$options = getopt('', array(
'dsn:',
));
if (empty($options)) {
die('Usage: '.$argv[0].' --dsn="pgsql:host=localhost;dbname=miniflux2;user=postgres;password=postgres"'.PHP_EOL);
}
function migrate_user(PDO $dst, array $user, array $settings)
{
$rq = $dst->prepare('
INSERT INTO users (
username,
password,
is_admin,
language
) VALUES (?, ?, ?, ?) RETURNING id');
$rq->execute(array(
strtolower($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,
strtolower($user['username']),
isset($user['fever_token']) ? $user['fever_token'] : '',
isset($user['fever_api_key']) ? $user['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, fever_api_key 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;
}