Merge pull request #660 from fabrixxm/moveme

uimport: check table columns before import
This commit is contained in:
friendica 2013-04-03 17:36:40 -07:00
commit 1e54f0022f

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* import account file exported from mod/uexport * import account file exported from mod/uexport
* args: * args:
@ -8,242 +9,264 @@
require_once("include/Photo.php"); require_once("include/Photo.php");
define("IMPORT_DEBUG", False); define("IMPORT_DEBUG", False);
function last_insert_id(){ function last_insert_id() {
global $db; global $db;
if (IMPORT_DEBUG) return 1; if (IMPORT_DEBUG)
if($db->mysqli){ return 1;
$thedb = $db->getdb(); if ($db->mysqli) {
return $thedb->insert_id; $thedb = $db->getdb();
} else { return $thedb->insert_id;
return mysql_insert_id(); } else {
} return mysql_insert_id();
} }
}
function last_error(){
global $db; function last_error() {
return $db->error; global $db;
} return $db->error;
}
function db_import_assoc($table, $arr){
if (IMPORT_DEBUG) return true; /**
if (isset($arr['id'])) unset($arr['id']); * Remove columns from array $arr that aren't in table $table
$cols = implode("`,`", array_map('dbesc', array_keys($arr))); *
$vals = implode("','", array_map('dbesc', array_values($arr))); * @param string $table Table name
$query = "INSERT INTO `$table` (`$cols`) VALUES ('$vals')"; * @param array &$arr Column=>Value array from json (by ref)
logger("uimport: $query",LOGGER_TRACE); */
return q($query); function check_cols($table, &$arr) {
} $query = sprintf("SHOW COLUMNS IN `%s`", dbesc($table));
logger("uimport: $query", LOGGER_DEBUG);
$r = q($query);
$tcols = array();
// get a plain array of column names
foreach ($r as $tcol) {
$tcols[] = $tcol['Field'];
}
// remove inexistent columns
foreach ($arr as $icol => $ival) {
if (!in_array($icol, $tcols)) {
unset($arr[$icol]);
}
}
}
/**
* Import data into table $table
*
* @param string $table Table name
* @param array $arr Column=>Value array from json
*/
function db_import_assoc($table, $arr) {
if (isset($arr['id']))
unset($arr['id']);
check_cols($table, $arr);
$cols = implode("`,`", array_map('dbesc', array_keys($arr)));
$vals = implode("','", array_map('dbesc', array_values($arr)));
$query = "INSERT INTO `$table` (`$cols`) VALUES ('$vals')";
logger("uimport: $query", LOGGER_TRACE);
if (IMPORT_DEBUG)
return true;
return q($query);
}
function import_cleanup($newuid) { function import_cleanup($newuid) {
q("DELETE FROM `user` WHERE uid = %d", $newuid); q("DELETE FROM `user` WHERE uid = %d", $newuid);
q("DELETE FROM `contact` WHERE uid = %d", $newuid); q("DELETE FROM `contact` WHERE uid = %d", $newuid);
q("DELETE FROM `profile` WHERE uid = %d", $newuid); q("DELETE FROM `profile` WHERE uid = %d", $newuid);
q("DELETE FROM `photo` WHERE uid = %d", $newuid); q("DELETE FROM `photo` WHERE uid = %d", $newuid);
q("DELETE FROM `group` WHERE uid = %d", $newuid); q("DELETE FROM `group` WHERE uid = %d", $newuid);
q("DELETE FROM `group_member` WHERE uid = %d", $newuid); q("DELETE FROM `group_member` WHERE uid = %d", $newuid);
q("DELETE FROM `pconfig` WHERE uid = %d", $newuid); q("DELETE FROM `pconfig` WHERE uid = %d", $newuid);
} }
function import_account(&$a, $file) { function import_account(&$a, $file) {
logger("Start user import from ".$file['tmp_name']); logger("Start user import from " . $file['tmp_name']);
/* /*
STEPS STEPS
1. checks 1. checks
2. replace old baseurl with new baseurl 2. replace old baseurl with new baseurl
3. import data (look at user id and contacts id) 3. import data (look at user id and contacts id)
4. archive non-dfrn contacts 4. archive non-dfrn contacts
5. send message to dfrn contacts 5. send message to dfrn contacts
*/ */
$account = json_decode(file_get_contents($file['tmp_name']), true);
if ($account === null) {
notice(t("Error decoding account file"));
return;
}
if (!x($account, 'version')) {
notice(t("Error! No version data in file! This is not a Friendica account file?"));
return;
}
if ($account['schema'] != DB_UPDATE_VERSION) {
notice(t("Error! I can't import this file: DB schema version is not compatible."));
return;
}
$account = json_decode(file_get_contents($file['tmp_name']), true);
if ($account===null) {
notice(t("Error decoding account file"));
return;
}
if (!x($account, 'version')) {
notice(t("Error! No version data in file! This is not a Friendica account file?"));
return;
}
if ($account['schema'] != DB_UPDATE_VERSION) {
notice(t("Error! I can't import this file: DB schema version is not compatible."));
return;
}
// check for username // check for username
$r = q("SELECT uid FROM user WHERE nickname='%s'", $account['user']['nickname']); $r = q("SELECT uid FROM user WHERE nickname='%s'", $account['user']['nickname']);
if ($r===false) { if ($r === false) {
logger("uimport:check nickname : ERROR : ".last_error(), LOGGER_NORMAL); logger("uimport:check nickname : ERROR : " . last_error(), LOGGER_NORMAL);
notice(t('Error! Cannot check nickname')); notice(t('Error! Cannot check nickname'));
return; return;
} }
if (count($r)>0) { if (count($r) > 0) {
notice(sprintf(t("User '%s' already exists on this server!"),$account['user']['nickname'])); notice(sprintf(t("User '%s' already exists on this server!"), $account['user']['nickname']));
return; return;
} }
$oldbaseurl = $account['baseurl']; $oldbaseurl = $account['baseurl'];
$newbaseurl = $a->get_baseurl(); $newbaseurl = $a->get_baseurl();
$olduid = $account['user']['uid']; $olduid = $account['user']['uid'];
unset($account['user']['uid']);
foreach($account['user'] as $k => &$v) {
$v = str_replace($oldbaseurl, $newbaseurl, $v);
}
unset($account['user']['uid']);
// import user foreach ($account['user'] as $k => &$v) {
$r = db_import_assoc('user', $account['user']); $v = str_replace($oldbaseurl, $newbaseurl, $v);
if ($r===false) { }
//echo "<pre>"; var_dump($r, $query, mysql_error()); killme();
logger("uimport:insert user : ERROR : ".last_error(), LOGGER_NORMAL);
notice(t("User creation error"));
return;
}
$newuid = last_insert_id();
//~ $newuid = 1;
foreach($account['profile'] as &$profile) { // import user
foreach($profile as $k=>&$v) { $r = db_import_assoc('user', $account['user']);
$v = str_replace($oldbaseurl, $newbaseurl, $v); if ($r === false) {
foreach(array("profile","avatar") as $k) //echo "<pre>"; var_dump($r, $query, mysql_error()); killme();
$v = str_replace($newbaseurl."/photo/".$k."/".$olduid.".jpg", $newbaseurl."/photo/".$k."/".$newuid.".jpg", $v); logger("uimport:insert user : ERROR : " . last_error(), LOGGER_NORMAL);
} notice(t("User creation error"));
$profile['uid'] = $newuid; return;
$r = db_import_assoc('profile', $profile); }
if ($r===false) { $newuid = last_insert_id();
logger("uimport:insert profile ".$profile['profile-name']." : ERROR : ".last_error(), LOGGER_NORMAL); //~ $newuid = 1;
info(t("User profile creation error"));
import_cleanup($newuid);
return;
}
}
$errorcount=0;
foreach($account['contact'] as &$contact) {
if ($contact['uid'] == $olduid && $contact['self'] == '1'){
foreach($contact as $k=>&$v) {
$v = str_replace($oldbaseurl, $newbaseurl, $v);
foreach(array("profile","avatar","micro") as $k)
$v = str_replace($newbaseurl."/photo/".$k."/".$olduid.".jpg", $newbaseurl."/photo/".$k."/".$newuid.".jpg", $v);
}
}
if ($contact['uid'] == $olduid && $contact['self'] == '0') {
switch ($contact['network']){
case NETWORK_DFRN:
// send relocate message (below)
break;
case NETWORK_ZOT:
// TODO handle zot network
break;
case NETWORK_MAIL2:
// TODO ?
break;
case NETWORK_FEED:
case NETWORK_MAIL:
// Nothing to do
break;
default:
// archive other contacts
$contact['archive'] = "1";
}
}
$contact['uid'] = $newuid;
$r = db_import_assoc('contact', $contact);
if ($r===false) {
logger("uimport:insert contact ".$contact['nick'].",".$contact['network']." : ERROR : ".last_error(), LOGGER_NORMAL);
$errorcount++;
} else {
$contact['newid'] = last_insert_id();
}
}
if ($errorcount>0) {
notice( sprintf(tt("%d contact not imported", "%d contacts not imported", $errorcount), $errorcount) );
}
foreach($account['group'] as &$group) {
$group['uid'] = $newuid;
$r = db_import_assoc('group', $group);
if ($r===false) {
logger("uimport:insert group ".$group['name']." : ERROR : ".last_error(), LOGGER_NORMAL);
} else {
$group['newid'] = last_insert_id();
}
}
foreach($account['group_member'] as &$group_member) {
$group_member['uid'] = $newuid;
$import = 0;
foreach($account['group'] as $group) {
if ($group['id'] == $group_member['gid'] && isset($group['newid'])) {
$group_member['gid'] = $group['newid'];
$import++;
break;
}
}
foreach($account['contact'] as $contact) {
if ($contact['id'] == $group_member['contact-id'] && isset($contact['newid'])) {
$group_member['contact-id'] = $contact['newid'];
$import++;
break;
}
}
if ($import==2) {
$r = db_import_assoc('group_member', $group_member);
if ($r===false) {
logger("uimport:insert group member ".$group_member['id']." : ERROR : ".last_error(), LOGGER_NORMAL);
}
}
}
foreach ($account['profile'] as &$profile) {
foreach ($profile as $k => &$v) {
foreach($account['photo'] as &$photo) { $v = str_replace($oldbaseurl, $newbaseurl, $v);
$photo['uid'] = $newuid; foreach (array("profile", "avatar") as $k)
$photo['data'] = hex2bin($photo['data']); $v = str_replace($newbaseurl . "/photo/" . $k . "/" . $olduid . ".jpg", $newbaseurl . "/photo/" . $k . "/" . $newuid . ".jpg", $v);
}
$p = new Photo($photo['data'], $photo['type']); $profile['uid'] = $newuid;
$r = $p->store( $r = db_import_assoc('profile', $profile);
$photo['uid'], if ($r === false) {
$photo['contact-id'], //0 logger("uimport:insert profile " . $profile['profile-name'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
$photo['resource-id'], info(t("User profile creation error"));
$photo['filename'], import_cleanup($newuid);
$photo['album'], return;
$photo['scale'], }
$photo['profile'], //1 }
$photo['allow_cid'],
$photo['allow_gid'], $errorcount = 0;
$photo['deny_cid'], foreach ($account['contact'] as &$contact) {
$photo['deny_gid'] if ($contact['uid'] == $olduid && $contact['self'] == '1') {
); foreach ($contact as $k => &$v) {
$v = str_replace($oldbaseurl, $newbaseurl, $v);
if ($r===false) { foreach (array("profile", "avatar", "micro") as $k)
logger("uimport:insert photo ".$photo['resource-id'].",". $photo['scale']. " : ERROR : ".last_error(), LOGGER_NORMAL); $v = str_replace($newbaseurl . "/photo/" . $k . "/" . $olduid . ".jpg", $newbaseurl . "/photo/" . $k . "/" . $newuid . ".jpg", $v);
} }
} }
if ($contact['uid'] == $olduid && $contact['self'] == '0') {
foreach($account['pconfig'] as &$pconfig) { switch ($contact['network']) {
$pconfig['uid'] = $newuid; case NETWORK_DFRN:
$r = db_import_assoc('pconfig', $pconfig); // send relocate message (below)
if ($r===false) { break;
logger("uimport:insert pconfig ".$pconfig['id']. " : ERROR : ".last_error(), LOGGER_NORMAL); case NETWORK_ZOT:
} // TODO handle zot network
} break;
case NETWORK_MAIL2:
// send relocate messages // TODO ?
proc_run('php', 'include/notifier.php', 'relocate' , $newuid); break;
case NETWORK_FEED:
info(t("Done. You can now login with your username and password")); case NETWORK_MAIL:
goaway( $a->get_baseurl() ."/login"); // Nothing to do
break;
default:
// archive other contacts
$contact['archive'] = "1";
}
}
$contact['uid'] = $newuid;
$r = db_import_assoc('contact', $contact);
if ($r === false) {
logger("uimport:insert contact " . $contact['nick'] . "," . $contact['network'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
$errorcount++;
} else {
$contact['newid'] = last_insert_id();
}
}
if ($errorcount > 0) {
notice(sprintf(tt("%d contact not imported", "%d contacts not imported", $errorcount), $errorcount));
}
foreach ($account['group'] as &$group) {
$group['uid'] = $newuid;
$r = db_import_assoc('group', $group);
if ($r === false) {
logger("uimport:insert group " . $group['name'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
} else {
$group['newid'] = last_insert_id();
}
}
foreach ($account['group_member'] as &$group_member) {
$group_member['uid'] = $newuid;
$import = 0;
foreach ($account['group'] as $group) {
if ($group['id'] == $group_member['gid'] && isset($group['newid'])) {
$group_member['gid'] = $group['newid'];
$import++;
break;
}
}
foreach ($account['contact'] as $contact) {
if ($contact['id'] == $group_member['contact-id'] && isset($contact['newid'])) {
$group_member['contact-id'] = $contact['newid'];
$import++;
break;
}
}
if ($import == 2) {
$r = db_import_assoc('group_member', $group_member);
if ($r === false) {
logger("uimport:insert group member " . $group_member['id'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
}
}
}
foreach ($account['photo'] as &$photo) {
$photo['uid'] = $newuid;
$photo['data'] = hex2bin($photo['data']);
$p = new Photo($photo['data'], $photo['type']);
$r = $p->store(
$photo['uid'], $photo['contact-id'], //0
$photo['resource-id'], $photo['filename'], $photo['album'], $photo['scale'], $photo['profile'], //1
$photo['allow_cid'], $photo['allow_gid'], $photo['deny_cid'], $photo['deny_gid']
);
if ($r === false) {
logger("uimport:insert photo " . $photo['resource-id'] . "," . $photo['scale'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
}
}
foreach ($account['pconfig'] as &$pconfig) {
$pconfig['uid'] = $newuid;
$r = db_import_assoc('pconfig', $pconfig);
if ($r === false) {
logger("uimport:insert pconfig " . $pconfig['id'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
}
}
// send relocate messages
proc_run('php', 'include/notifier.php', 'relocate', $newuid);
info(t("Done. You can now login with your username and password"));
goaway($a->get_baseurl() . "/login");
} }