1, 'xiffy' => 2, 'roel' => 3, '_default' => 1)
* @param aMapCategoryToNucleusId
* Similar to $aMapUserToNucleusId, but this array maps category names to
* category ids. Please note that the category IDs need to come from the
* same blog as $iBlogId
* example: array('general' => 11, 'funny' => 33)
* @param strCallback
* name of a callback function to be called on each item. Such a callback
* function should have a format like:
* function myCallback(&$data)
* where $data is an associative array with all item data ('title','body',
* ...)
*/
function BlogImport($iBlogId = -1, $aOptions = array('ReadNamesOnly' => 0), $aMapUserToNucleusId = array(), $aMapCategoryToNucleusId = array(), $strCallback = '') {
global $manager;
$this->iBlog = $iBlogId;
if ($iBlogId != -1)
$this->oBlog =& $manager->getBlog($iBlogId);
else
$this->oBlog = 0;
$this->aOptions = $aOptions;
$this->aMapUserToNucleusId = $aMapUserToNucleusId;
$this->aMapCategoryToNucleusId = $aMapCategoryToNucleusId;
$this->strCallback = $strCallback;
$this->aMapIdToNucleusId = array();
$this->bReadNamesOnly = $this->aOptions['ReadNamesOnly'] == 1;
$this->aCategoryNames = array();
$this->aAuthorNames = array();
// disable magic_quotes_runtime if it's turned on
set_magic_quotes_runtime(0);
// debugging mode?
$this->bDebug = 0;
// XML file pointer
$this->fp = 0;
// to maintain track of where we are inside the XML file
$this->inXml = 0;
$this->inData = 0;
$this->inItem = 0;
$this->inComment = 0;
$this->aCurrentItem = $this->_blankItem();
$this->aCurrentComment = $this->_blankComment();
// character data pile
$this->cdata = '';
// init XML parser
$this->parser = xml_parser_create();
xml_set_object($this->parser, $this);
xml_set_element_handler($this->parser, 'startElement', 'endElement');
xml_set_character_data_handler($this->parser, 'characterData');
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
// TODO: add data checking
$this->bValid = 1;
// data structures
$this->strErrorMessage = '';
}
/**
* Gets the import library version
*/
function getVersion() {
return '0.2';
}
/**
* Returns an array with all the author names used in the file (only
* the authors of items are included)
*
* @require importXmlFile should be called prior to calling this
*/
function getAuthorNames() {
return $this->aAuthorNames;
}
/**
* Returns an array with all the category names used in the file
*
* @require importXmlFile should be called prior to calling this
*/
function getCategoryNames() {
return $this->aCategoryNames;
}
/**
* Imports an XML file into a given blog
*
* also fills $this->aMapIdToNucleusId
* array with info for each item having a Nucleus ID that is different
* from the original ID
* example: array(9999 => 1, 1234 => 2, 12 => 3)
*
* @param strXmlFile
* Location of the XML file. The XML file must be in the correct
* Nucleus import format
* @returns
* 0 on failure. Use getLastError() to get error message
* 1 on success
*
*/
function importXmlFile($strXmlFile) {
$this->resetErrorMessage();
flush();
if (!$this->bValid)
return $this->setErrorMessage('BlogImport object is invalid');
if (!@file_exists($strXmlFile))
return $this->setErrorMessage($strXmlFile . ' does not exist');
if (!@is_readable($strXmlFile))
return $this->setErrorMessage($strXmlFile . ' is not readable');
// open file
$this->fp = @fopen($strXmlFile, 'r');
if (!$this->fp)
return $this->setErrorMessage('Failed to open file/URL');
// here we go!
$this->inXml = 1;
// parse file contents
while ($buffer = fread($this->fp, 4096)) {
$err = xml_parse( $this->parser, $buffer, feof($this->fp) );
if (!$err && $this->bDebug)
echo 'ERROR: ', xml_error_string(xml_get_error_code($this->parser)), ' ';
}
// all done
$this->inXml = 0;
fclose($this->fp);
return 1;
}
/**
* Identical to importXmlFile, but takes an almost-ready-for-addition array
*
* @param aData
* Array with item data, as prepared by import_fromXML
*
* @returns
* 0 on failure. Use getLastError() to get error message
* 1 on success
*/
function importOneItem(&$aData) {
$this->resetErrorMessage();
// - do some logic to determine nucleus users and categories
// * find member id
// * find blog id
// * find category id
$aData['nucleus_blogid'] = $this->iBlog;
$aData['nucleus_catid'] = $this->_findCategoryId($aData['category']);
$aData['nucleus_memberid'] = $this->_findMemberId($aData['author']);
if ($aData['nucleus_memberid'] == 0) {
$aData['nucleus_memberid'] = $this->aMapUserToNucleusId['_default'];
}
// - apply logic to comments
foreach (array_keys($aData['comments']) as $key) {
// * find member id
$aData['comments'][$key]['nucleus_memberid']
= $this->_findMemberId($aData['comments'][$key]['author']);
// * extract authorid
if ($aData['comments'][$key]['nucleus_memberid'] == 0) {
$url = $aData['comments'][$key]['url'];
$email = $aData['comments'][$key]['email'];
$authid = $aData['comments'][$key]['authorid'];
if (!$authid && $url)
$aData['comments'][$key]['authorid'] = $url;
else if (!$authid && $email)
$aData['comments'][$key]['authorid'] = $email;
}
}
// - call callback
if ($this->strCallback && function_exists($this->strCallback)) {
call_user_func_array($this->strCallback, array(&$aData));
}
if ($this->bDebug) {
echo '
';
print_r($aData);
echo '
';
}
// - insert item into nucleus database
$iNewId = $this->sql_addToItem(
$aData['title'],
$aData['body'],
$aData['extended'],
$aData['nucleus_blogid'],
$aData['nucleus_memberid'],
$aData['timestamp'],
($aData['itemstatus'] == 'open') ? 0 : 1,
$aData['nucleus_catid'],
$aData['posvotes'],
$aData['negvotes']
);
// - store id mapping if needed
$aData['nucleus_id'] = $iNewId;
if ($aData['nucleus_id'] != $aData['id'])
$this->aMapIdToNucleusId[$aData['id']] = $aData['nucleus_id'];
// - insert comments into nucleus database
foreach ($aData['comments'] as $comment) {
$cId = $this->sql_addToComments(
$comment['author'],
$comment['authorid'],
$comment['body'],
$aData['nucleus_blogid'],
$aData['nucleus_id'],
$comment['nucleus_memberid'],
$comment['timestamp'],
$comment['host'],
$comment['ip']
);
}
echo ' .'; // progress indicator
flush();
return 1;
}
function getHtmlCode($what) {
ob_start();
switch($what) {
// ----------------------------------------------------------------------------------------
case 'NucleusMemberOptions':
$res = DB::getResult('SELECT mname as text, mnumber as value FROM '.sql_table('member'));
foreach ( $res as $row )
{
echo '';
}
break;
// ----------------------------------------------------------------------------------------
case 'NucleusBlogSelect':
$query = 'SELECT bname as text, bnumber as value FROM '.sql_table('blog');
$template['name'] = 'blogid';
$template['selected'] = $CONF['DefaultBlog'];
echo showlist($query,'select',$template);
break;
// ----------------------------------------------------------------------------------------
case 'ConvertSelectMembers':
?>
Assign Members to Authors
Below is a list of all the authors that Nucleus could discover (only authors that have posted at least one entry are listed). Please assign a Nucleus Member to all of these authors.
Author
Nucleus Member
Blog Admin?
getAuthorNames();
// get HTML code for selection list
$optionsHtml = $this->getHtmlCode('NucleusMemberOptions');
$idx = 0;
while ($a_name = array_pop($authors)) {
?>
Default Member
Assign Categories
Below is a list of all the categories that Nucleus could discover (only categories that have been used at least once are listed). Please assign a Nucleus Category to all of these categories.
Category
Nucleus Category
getCategoryNames();
// get HTML code for selection list
$optionsHtml = $this->getHtmlCode('NucleusCategoryOptions');
$idx = 0;
while ($a_name = array_pop($catnames)) {
?>
Choose Destination Weblog
There are two options: you can either choose an existing blog to add the entries into, or you can choose to create a new weblog.
getHtmlCode('NucleusBlogSelect'); ?>
New blog name:
Blog owner:
Do the conversion!
Note: Clicking the button once is enough, even if it takes a while to complete.
Creating new blog';
echo '
Your new weblog has been created.
';
return $nucleus_blogid;
} else {
return $blogid;
}
}
function getFromRequest($what) {
$aResult = array();
switch ($what) {
case 'authors':
$authorcount = intPostVar('authorcount');
$author = requestArray('author');
$memberid = requestIntArray('memberid');
$isadmin = requestIntArray('admin');
for ($i=0;$i<$authorcount;$i++) {
$authorname = undoMagic($author[$i]);
// add authors to team
$this->oBlog->addTeamMember(intval($memberid[$i]),intval($isadmin[$i]));
$aResult[$authorname] = $memberid[$i];
}
$this->aMapUserToNucleusId = $aResult;
break;
case 'categories':
// TODO
$this->aMapCategoryToNucleusId = $aResult;
break;
}
return $aResult;
}
function _findCategoryId($name) {
$catid = @$this->aMapCategoryToNucleusId[$name];
if (!$catid && $this->oBlog)
// get default category for weblog
$catid = $this->oBlog->getDefaultCategory();
return $catid;
}
function _findMemberId($name) {
$memberid = intval(@$this->aMapUserToNucleusId[$name]);
return $memberid;
}
/**
* Returns the last error message. Use it to find out the reason for failure
*/
function getLastError() {
return $this->strErrorMessage;
}
function resetErrorMessage() {
$this->strErrorMessage = '';
}
function setErrorMessage($strMsg) {
$this->strErrorMessage = $strMsg;
return 0;
}
/**
* Called by XML parser for each new start element encountered
*/
function startElement($parser, $name, $attrs) {
if ($this->bDebug) echo 'START: ', $name, ' ';
switch ($name) {
case 'blog':
$this->inData = 1;
$this->strImportFileVersion = $attrs['version'];
// TODO: check version number
break;
case 'item':
$this->inItem = 1;
$this->aCurrentItem = $this->_blankItem($attrs['id']);
if (@$attrs['commentsOnly'] == 'true')
$this->aCurrentItem['commentsOnly'] = 1;
else
$this->aCurrentItem['commentsOnly'] = 0;
break;
case 'timestamp':
if ($this->inItem || $this->inComment) {
// store time format
$this->currentTSFormat = $attrs['type'];
}
break;
case 'author':
case 'title':
case 'body':
case 'extended':
case 'category':
case 'itemstatus':
case 'posvotes':
case 'negvotes':
// nothing to do
break;
case 'comment':
if ($this->inItem) {
$this->inComment = 1;
$this->aCurrentComment = $this->_blankComment($attrs['id']);
}
break;
case 'email':
case 'url':
case 'authorid':
case 'host':
case 'ip':
// nothing to do
break;
default:
echo 'UNEXPECTED TAG: ' , $name , ' ';
break;
}
// character data never contains other tags
$this->clearCharacterData();
}
/**
* Called by the XML parser for each closing tag encountered
*/
function endElement($parser, $name) {
if ($this->bDebug) echo 'END: ', $name, ' ';
switch ($name) {
case 'blog':
$this->inData = 0;
break;
case 'item':
if (!$this->bReadNamesOnly) {
// write to database
// TODO: check if succes or failure
$this->importOneItem($this->aCurrentItem);
}
$this->inItem = 0;
// initialize item structure
$this->aCurrentItem = $this->_blankItem();
break;
case 'timestamp':
$timestamp = $this->getTime($this->getCharacterData(), $this->currentTSFormat);
if ($this->inComment)
$this->aCurrentComment['timestamp'] = $timestamp;
else if ($this->inItem)
$this->aCurrentItem['timestamp'] = $timestamp;
break;
case 'author':
if ($this->inItem && !$this->inComment)
$this->_addAuthorName($this->getCharacterData());
if ($this->inComment)
$this->aCurrentComment['author'] = $this->getCharacterData();
else if ($this->inItem)
$this->aCurrentItem['author'] = $this->getCharacterData();
break;
case 'title':
if ($this->inComment)
$this->aCurrentComment['title'] = $this->getCharacterData();
else if ($this->inItem)
$this->aCurrentItem['title'] = $this->getCharacterData();
break;
case 'body':
if ($this->inComment)
$this->aCurrentComment['body'] = $this->getCharacterData();
else if ($this->inItem)
$this->aCurrentItem['body'] = $this->getCharacterData();
break;
case 'extended':
if ($this->inItem)
$this->aCurrentItem['extended'] = $this->getCharacterData();
break;
case 'category':
$this->_addCategoryName($this->getCharacterData());
if ($this->inItem && !$this->aCurrentItem['category']) {
$this->aCurrentItem['category'] = $this->getCharacterData();
}
break;
case 'itemstatus':
if ($this->inItem)
$this->aCurrentItem['itemstatus'] = $this->getCharacterData();
break;
case 'posvotes':
if ($this->inItem)
$this->aCurrentItem['posvotes'] = $this->getCharacterData();
break;
case 'negvotes':
if ($this->inItem)
$this->aCurrentItem['negvotes'] = $this->getCharacterData();
break;
case 'comment':
if ($this->inComment) {
array_push($this->aCurrentItem['comments'], $this->aCurrentComment);
$this->aCurrentComment = $this->_blankComment();
$this->inComment = 0;
}
break;
case 'email':
if ($this->inComment)
$this->aCurrentComment['email'] = $this->getCharacterData();
break;
case 'url':
if ($this->inComment)
$this->aCurrentComment['url'] = $this->getCharacterData();
break;
case 'authorid':
if ($this->inComment)
$this->aCurrentComment['authorid'] = $this->getCharacterData();
break;
case 'host':
if ($this->inComment)
$this->aCurrentComment['host'] = $this->getCharacterData();
break;
case 'ip':
if ($this->inComment)
$this->aCurrentComment['ip'] = $this->getCharacterData();
break;
default:
echo 'UNEXPECTED TAG: ' , $name, ' ';
break;
}
$this->clearCharacterData();
}
/**
* Called by XML parser for data inside elements
*/
function characterData ($parser, $data) {
if ($this->bDebug) echo 'NEW DATA: ', Entity::hsc($data), ' ';
$this->cdata .= $data;
}
/**
* Returns the data collected so far
*/
function getCharacterData() {
return $this->cdata;
}
/**
* Clears the data buffer
*/
function clearCharacterData() {
$this->cdata = '';
}
/**
* Parses a given string into a unix timestamp.
*
* @param strTime
* String, formatted as given in $strFormat
* @param strFormat
* Multiple date formats are supported:
* 'unix': plain unix timestamp (numeric)
* 'blogger': for blogger import: MM/DD/YYYY hh:MM:SS AM
*/
function getTime($strTime, $strFormat = 'unix') {
$strFormat = strtolower($strFormat);
switch($strFormat) {
case 'unix':
return intval($strTime);
case 'blogger':
// 7/24/2000 11:27:13 AM
if (eregi("(.*)/(.*)/(.*) (.*):(.*):(.*) (.*)",$strTime,$regs) != false) {
if (($regs[7] == "PM") && ($regs[4] != "12"))
$regs[4] += 12;
return mktime($regs[4],$regs[5],$regs[6],$regs[1],$regs[2],$regs[3]);
} else {
return 0;
}
}
}
function _blankItem($id = -1) {
return array(
'id' => $id,
'commentsOnly' => 0,
'timestamp' => time(),
'author' => '',
'title' => '',
'body' => '',
'extended' => '',
'category' => '',
'itemstatus' => 'open',
'posvotes' => 0,
'negvotes' => 0,
'comments' => array()
);
}
function _blankComment($id = -1) {
return array(
'id' => $id,
'timestamp' => time(),
'author' => '',
'title' => '',
'body' => '',
'email' => '',
'url' => '',
'authorid' => '',
'host' => '',
'ip' => ''
);
}
function _addAuthorName($name) {
if (!in_array($name, $this->aAuthorNames))
array_push($this->aAuthorNames, $name);
}
function _addCategoryName($name) {
if (!in_array($name, $this->aCategoryNames))
array_push($this->aCategoryNames, $name);
}
function sql_addToItem($title, $body, $more, $blogid, $authorid, $timestamp, $closed, $category, $karmapos, $karmaneg) {
$title = DB::quoteValue(trim($title));
$body = DB::quoteValue(trim($body));
$more = DB::quoteValue(trim($more));
$timestamp = DB::formatDateTime($timestamp);
$query = 'INSERT INTO '.sql_table('item').' (ITITLE, IBODY, IMORE, IBLOG, IAUTHOR, ITIME, ICLOSED, IKARMAPOS, IKARMANEG, ICAT) '
. "VALUES ($title, $body, $more, $blogid, $authorid, $timestamp, $closed, $karmapos, $karmaneg, $category)";
if ( DB::execute($query) === FALSE )
{
die('Error while executing query: ' . $query);
}
return DB::getInsertId();
}
function sql_addToBlog($name, $shortname, $ownerid) {
$name = DB::quoteValue($name);
$shortname = DB::quoteValue($shortname);
// create new category first
DB::execute('INSERT INTO '.sql_table('category')." (CNAME, CDESC) VALUES ('General','Items that do not fit in another category')");
$defcat = DB::getInsertId();
$query = 'INSERT INTO '.sql_table('blog')." (BNAME, BSHORTNAME, BCOMMENTS, BMAXCOMMENTS, BDEFCAT) VALUES ($name, $shortname, 1, 0, $defcat)";
if ( DB::execute($query) === FALSE )
{
die('Error while executing query: ' . $query);
}
$id = DB::getInsertId();
// update category row so it links to blog
DB::execute('UPDATE ' . sql_table('category') . ' SET cblog=' . intval($id). ' WHERE catid=' . intval($defcat));
BlogImport::sql_addToTeam($id,$ownerid,1);
return $id;
}
function sql_addToComments($name, $url, $body, $blogid, $itemid, $memberid, $timestamp, $host, $ip='') {
$name = DB::quoteValue($name);
$url = DB::quoteValue($url);
$body = DB::quoteValue(trim($body));
$host = DB::quoteValue($host);
$ip = DB::quoteValue($ip);
$timestamp = DB::formatDateTime($timestamp);
$query = 'INSERT INTO '.sql_table('comment')
. ' (CUSER, CMAIL, CMEMBER, CBODY, CITEM, CTIME, CHOST, CBLOG, CIP) '
. "VALUES ($name, $url, $memberid, $body, $itemid, $timestamp, $host, $blogid, $ip)";
if ( DB::execute($query) === FALSE )
{
die('Error while executing query: ' . $query);
}
return DB::getInsertId();
}
function sql_addToTeam($blogid, $memberid, $admin) {
$query = 'INSERT INTO '.sql_table('team').' (TMEMBER, TBLOG, TADMIN) '
. "VALUES ($memberid, $blogid, $admin)";
if ( DB::execute($query) === FALSE )
{
die('Error while executing query: ' . $query);
}
return DB::getInsertId();
}
}
// some sort of version checking
$ver = convert_getNucleusVersion();
if ($ver > 250)
convert_doError("You should check the Nucleus website for updates to this convert tool. This one might not work with your current Nucleus installation.");
// make sure the request variables get reqistered in the global scope
// Doing this should be avoided on code rewrite (this is a potential security risk)
if ((phpversion() >= "4.1.0") && (ini_get("register_globals") == 0)) {
@import_request_variables("gp",'');
}
/** this function gets the nucleus version, even if the getNucleusVersion
* function does not exist yet
* return 96 for all versions < 100
*/
function convert_getNucleusVersion() {
if (!function_exists('getNucleusVersion')) return 96;
return getNucleusVersion();
}
// TODO: remove this function (replaced by BlogImport::sql_addToItem)
function convert_addToItem($title, $body, $more, $blogid, $authorid, $timestamp, $closed, $category, $karmapos, $karmaneg) {
$title = DB::quoteValue(trim($title));
$body = DB::quoteValue(trim($body));
$more = DB::quoteValue(trim($more));
$query = 'INSERT INTO '.sql_table('item').' (ITITLE, IBODY, IMORE, IBLOG, IAUTHOR, ITIME, ICLOSED, IKARMAPOS, IKARMANEG, ICAT) '
. "VALUES ($title, $body, $more, $blogid, $authorid, '$timestamp', $closed, $karmapos, $karmaneg, $category)";
if ( DB::execute($query) === FALSE )
{
die('Error while executing query: ' . $query);
}
return DB::getInsertId();
}
// TODO: remove this function (replaced by BlogImport::sql_addToBlog)
function convert_addToBlog($name, $shortname, $ownerid) {
$name = DB::quoteValue($name);
$shortname = DB::quoteValue($shortname);
// create new category first
DB::execute('INSERT INTO '.sql_table('category')." (CNAME, CDESC) VALUES ('General','Items that do not fit in another categort')");
$defcat = DB::getInsertId();
$query = 'INSERT INTO '.sql_table('blog')." (BNAME, BSHORTNAME, BCOMMENTS, BMAXCOMMENTS, BDEFCAT) VALUES ($name, $shortname, 1, 0, $defcat)";
if ( DB::execute($query) === FALSE )
{
die('Error while executing query: ' . $query);
}
$id = DB::getInsertId();
convert_addToTeam($id,$ownerid,1);
return $id;
}
// TODO: remove this function (replaced by BlogImport::sql_addToComments)
function convert_addToComments($name, $url, $body, $blogid, $itemid, $memberid, $timestamp, $host, $ip='') {
$name = DB::quoteValue($name);
$url = DB::quoteValue($url);
$body = DB::quoteValue(trim($body));
$host = DB::quoteValue($host);
$ip = DB::quoteValue($ip);
$query = 'INSERT INTO '.sql_table('comment')
. ' (CUSER, CMAIL, CMEMBER, CBODY, CITEM, CTIME, CHOST, CBLOG, CIP) '
. "VALUES ($name, $url, $memberid, $body, $itemid, '$timestamp', $host, $blogid, $ip)";
if ( DB::execute($query) === FALSE )
{
die("Error while executing query: " . $query);
}
return DB::getInsertId();
}
// TODO: remove this function (replaced by BlogImport::sql_addToTeam)
function convert_addToTeam($blogid, $memberid, $admin) {
$query = 'INSERT INTO '.sql_table('team').' (TMEMBER, TBLOG, TADMIN) '
. "VALUES ($memberid, $blogid, $admin)";
if ( DB::execute($query) === FALSE )
{
die("Error while executing query: " . $query);
}
return DB::getInsertId();
}
function convert_showLogin($type) {
convert_head();
?>