Version 1.2.1 ()
------------------------------------------------------------------------
+ * Updated Textile library to 2.0, by Lars Strojny
+
+ * Fix wrong entry timestamp used in comment feeds (garvinhicking)
+
+ * Highlighting searched words in entries now uses str_replace instead
+ of slower and possibly insecure preg_replace(). Thanks to
+ Dietrich Raisin!
+
+ * Updated WordPress imported to be able to import from a 2.3
+ structure (experimental). Also added WPXRSS import to the
+ generic RSS importer. (garvinhicking)
+
* Fix proper encoding of '%' sign when used in post titles
(garvinhicking)
global $serendipity;
mysql_select_db($this->data['name'], $db);
+ $dbn = false;
+
+ $target = $this->data['charset'];
+
+ switch($target) {
+ case 'native':
+ $dbn = SQL_CHARSET;
+ break;
+
+ case 'ISO-8859-1':
+ $dbn = 'latin1';
+ break;
+
+ case 'UTF-8':
+ $dbn = 'utf8';
+ break;
+ }
+
+ if ($dbn && $serendipity['dbNames']) {
+ mysql_query("SET NAMES " . $dbn, $db);
+ }
+
$return = &mysql_query($query, $db);
- mysql_select_db($serendipity['dbName'], $serendipity['dbConn']); $return = &mysql_query($query, $db);
+ mysql_select_db($serendipity['dbName'], $serendipity['dbConn']);
+ serendipity_db_reconnect();
return $return;
}
}
array('text' => RSS_IMPORT_BODYONLY,
'type' => 'bool',
'name' => 'bodyonly',
- 'value' => 'false'));
+ 'value' => 'false'),
+
+ array('text' => RSS_IMPORT_WPXRSS,
+ 'type' => 'bool',
+ 'name' => 'wpxrss',
+ 'value' => 'false')
+ );
}
function validateData() {
return true;
}
+ function import_wpxrss() {
+ // TODO: Backtranscoding to NATIVE charset. Currently only works with UTF-8.
+ $dry_run = false;
+
+ $serendipity['noautodiscovery'] = 1;
+ $uri = $this->data['url'];
+ require_once S9Y_PEAR_PATH . 'HTTP/Request.php';
+ serendipity_request_start();
+ $req = &new HTTP_Request($uri, array('allowRedirects' => true, 'maxRedirects' => 5));
+ $res = $req->sendRequest();
+
+ if (PEAR::isError($res) || $req->getResponseCode() != '200') {
+ serendipity_request_end();
+ echo IMPORT_FAILED . ': ' . htmlspecialchars($this->data['url']);
+ echo "<br />\n";
+ return false;
+ }
+
+ $fContent = $req->getResponseBody();
+ serendipity_request_end();
+ echo strlen($fContent) . " Bytes<br />\n";
+
+ if (version_compare(PHP_VERSION, '5.0') === -1) {
+ printf(UNMET_REQUIREMENTS, 'PHP >= 5.0');
+ echo "<br />\n";
+ return false;
+ }
+
+ $xml = simplexml_load_string($fContent);
+ unset($fContent);
+
+
+ /* ************* USERS **********************/
+ $_s9y_users = serendipity_fetchUsers();
+ $s9y_users = array();
+ if (is_array($s9y_users)) {
+ foreach ($_s9y_users as $v) {
+ $s9y_users[$v['realname']] = $v;
+ }
+ }
+
+ /* ************* CATEGORIES **********************/
+ $_s9y_cat = serendipity_fetchCategories('all');
+ $s9y_cat = array();
+ if (is_array($s9y_cat)) {
+ foreach ($_s9y_cat as $v) {
+ $s9y_cat[$v['category_name']] = $v['categoryid'];
+ }
+ }
+
+ $wp_ns = 'http://wordpress.org/export/1.0/';
+ $dc_ns = 'http://purl.org/dc/elements/1.1/';
+ $content_ns = 'http://purl.org/rss/1.0/modules/content/';
+
+ $wp_core = $xml->channel->children($wp_ns);
+ foreach($wp_core->category AS $idx => $cat) {
+ //TODO: Parent generation unknown.
+ $cat_name = (string)$cat->cat_name;
+ if (!isset($s9y_cat[$cat_name])) {
+ $cat = array('category_name' => $cat_name,
+ 'category_description' => '',
+ 'parentid' => 0,
+ 'category_left' => 0,
+ 'category_right' => 0);
+
+ printf(CREATE_CATEGORY, htmlspecialchars($cat_name));
+ echo "<br />\n";
+ if ($dry_run) {
+ $s9y_cat[$cat_name] = time();
+ } else {
+ serendipity_db_insert('category', $cat);
+ $s9y_cat[$cat_name] = serendipity_db_insert_id('category', 'categoryid');
+ }
+ }
+ }
+
+ /* ************* ITEMS **********************/
+ foreach($xml->channel->item AS $idx => $item) {
+ $wp_items = $item->children($wp_ns);
+ $dc_items = $item->children($dc_ns);
+ $content_items = $item->children($content_ns);
+
+ // TODO: Attachments not handled
+ if ((string)$wp_items->post_type == 'attachment' OR (string)$wp_items->post_type == 'page') {
+ continue;
+ }
+
+ $entry = array(
+ 'title' => (string)$item->title,
+ 'isdraft' => ((string)$wp_items->status == 'publish' ? 'false' : 'true'),
+ 'allow_comments' => ((string)$wp_items->comment_status == 'open' ? true : false),
+ 'categories' => array(),
+ 'body' => (string)$content_items->encoded
+ );
+
+ if (preg_match('@^([0-9]{4})\-([0-9]{2})\-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})$@', (string)$wp_items->post_date, $timematch)) {
+ $entry['timestamp'] = mktime($timematch[4], $timematch[5], $timematch[6], $timematch[2], $timematch[3], $timematch[1]);
+ } else {
+ $entry['timestamp'] = time();
+ }
+
+ if (isset($item->category[1])) {
+ foreach($item->category AS $idx => $category) {
+ $cstring=(string)$category;
+ if (!isset($s9y_cat[$cstring])) {
+ echo "WARNING: $category unset!<br />\n";
+ } else {
+ $entry['categories'][] = $s9y_cat[$cstring];
+ }
+ }
+ } else {
+ $cstring = (string)$item->category;
+ $entry['categories'][] = $s9y_cat[$cstring];
+ }
+
+ $wp_user = (string)$dc_items->creator;
+ if (!isset($s9y_users[$wp_user])) {
+ if ($dry_run) {
+ $s9y_users[$wp_user]['authorid'] = time();
+ } else {
+ $s9y_users[$wp_user]['authorid'] = serendipity_addAuthor($wp_user, md5(time()), $wp_user, '', USERLEVEL_EDITOR);
+ }
+ printf(CREATE_AUTHOR, htmlspecialchars($wp_user));
+ echo "<br />\n";
+ }
+
+ $entry['authorid'] = $s9y_users[$wp_user]['authorid'];
+
+ if ($dry_run) {
+ $id = time();
+ } else {
+ $id = serendipity_updertEntry($entry);
+ }
+
+ $s9y_cid = array(); // Holds comment ids to s9y ids association.
+ $c_i = 0;
+ foreach($wp_items->comment AS $comment) {
+ $c_i++;
+ $c_id = (string)$comment->comment_id;
+ $c_pid = (string)$comment->comment_parent;
+ $c_type = (string)$comment->comment_type;
+ if ($c_type == 'pingback') {
+ $c_type2 = 'PINGBACK';
+ } elseif ($c_type == 'trackback') {
+ $c_type2 = 'TRACKBACK';
+ } else {
+ $c_type2 = 'NORMAL';
+ }
+
+ $s9y_comment = array('entry_id ' => $id,
+ 'parent_id' => $s9y_cid[$c_pd],
+ 'author' => (string)$comment->comment_author,
+ 'email' => (string)$comment->comment_author_email,
+ 'url' => (string)$comment->comment_author_url,
+ 'ip' => (string)$comment->comment_author_IP,
+ 'status' => (empty($comment->comment_approved) || $comment->comment_approved == '1') ? 'approved' : 'pending',
+ 'subscribed'=> 'false',
+ 'body' => (string)$comment->comment_content,
+ 'type' => $c_type2);
+
+ if (preg_match('@^([0-9]{4})\-([0-9]{2})\-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})$@', (string)$comment->comment_date, $timematch)) {
+ $s9y_comment['timestamp'] = mktime($timematch[4], $timematch[5], $timematch[6], $timematch[2], $timematch[3], $timematch[1]);
+ } else {
+ $s9y_comment['timestamp'] = time();
+ }
+
+ if ($dry_run) {
+ $cid = time();
+ } else {
+ serendipity_db_insert('comments', $s9y_comment);
+ $cid = serendipity_db_insert_id('comments', 'id');
+ if ($s9y_comment['status'] == 'approved') {
+ serendipity_approveComment($cid, $id, true);
+ }
+ }
+ $s9y_cid[$c_id] = $cid;
+ }
+
+ echo "Entry '" . htmlspecialchars($entry['title']) . "' ($c_i comments) imported.<br />\n";
+ }
+ return true;
+ }
+
function import() {
global $serendipity;
+ if ($this->data['wpxrss']) {
+ return $this->import_wpxrss();
+ }
+
$c = &new Onyx_RSS($this->data['charset']);
$c->parse($this->data['url']);
$this->data['encoding'] = $c->rss['encoding'];
return 'Serendipity_Import_Generic';
/* vim: set sts=4 ts=4 expandtab : */
-?>
unset($users);
}
- /* Categories */
+ $no_cat = false;
+
+ /* Categories (WP < 2.3 style) */
$res = @$this->nativeQuery("SELECT cat_ID, cat_name, category_description, category_parent
FROM {$this->data['prefix']}categories
ORDER BY category_parent, cat_ID;", $wpdb);
if (!$res) {
- printf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($wpdb));
+ $no_cat = mysql_error($wpdb);
} else {
- if ($debug) echo "Importing categories...<br />\n";
+ if ($debug) echo "Importing categories (WP 2.2 style)...<br />\n";
// Get all the info we need
for ($x=0 ; $x<mysql_num_rows($res) ; $x++) {
if ($debug) echo "Rebuilt category tree.<br />\n";
}
+ /* Categories (WP >= 2.3 style) */
+ $res = @$this->nativeQuery("SELECT taxonomy.description AS category_description,
+ taxonomy.parent AS category_parent,
+ taxonomy.term_taxonomy_id AS cat_ID,
+ terms.name AS cat_name
+
+ FROM {$this->data['prefix']}term_taxonomy AS taxonomy
+
+ JOIN {$this->data['prefix']}terms AS terms
+ ON taxonomy.term_id = terms.term_id
+
+ WHERE taxonomy.taxonomy = 'category'
+ ORDER BY taxonomy.parent, taxonomy.term_taxonomy_id", $wpdb);
+ if (!$res && !$no_cat) {
+ $no_cat = mysql_error($wpdb);
+ } elseif ($res) {
+ $no_cat = false;
+ if ($debug) echo "Importing categories (WP 2.3 style)...<br />\n";
+
+ // Get all the info we need
+ for ($x=0 ; $x<mysql_num_rows($res) ; $x++) {
+ $categories[] = mysql_fetch_assoc($res);
+ }
+
+ // Insert all categories as top level (we need to know everyone's ID before we can represent the hierarchy).
+ for ($x=0, $c = sizeof($categories) ; $x < $c ; $x++) {
+ $cat = array('category_name' => $categories[$x]['cat_name'],
+ 'category_description' => $categories[$x]['category_description'],
+ 'parentid' => 0,
+ 'category_left' => 0,
+ 'category_right' => 0);
+
+ serendipity_db_insert('category', $this->strtrRecursive($cat));
+ $categories[$x]['categoryid'] = serendipity_db_insert_id('category', 'categoryid');
+
+ // Set association.
+ $assoc['categories'][$categories[$x]['cat_ID']] = $categories[$x]['categoryid'];
+ }
+
+ foreach ($categories as $cat) {
+ if ($cat['category_parent'] != 0) {
+ // Find the parent
+ $par_id = 0;
+ foreach ($categories as $possible_par) {
+ if ($possible_par['cat_ID'] == $cat['category_parent']) {
+ $par_id = $possible_par['categoryid'];
+ break;
+ }
+ }
+
+ if ($par_id != 0) {
+ serendipity_db_query("UPDATE {$serendipity['dbPrefix']}category
+ SET parentid={$par_id}
+ WHERE categoryid={$cat['categoryid']};");
+ }
+ }
+ }
+
+ // Clean memory
+ unset($categories);
+
+ if ($debug) echo "Imported categories.<br />\n";
+ if ($debug) echo "Rebuilding category tree...<br />\n";
+ serendipity_rebuildCategoryTree();
+ if ($debug) echo "Rebuilt category tree.<br />\n";
+ }
+ if ($no_cat) {
+ printf(COULDNT_SELECT_CATEGORY_INFO, $no_cat);
+ }
/* Entries */
if (serendipity_db_bool($this->data['import_all'])) {
unset($entries);
}
- /* Entry/category */
+ /* Entry/category (WP < 2.3 style)*/
+ $no_entrycat = false;
$res = @$this->nativeQuery("SELECT * FROM {$this->data['prefix']}post2cat;", $wpdb);
if (!$res) {
- printf(COULDNT_SELECT_ENTRY_INFO, mysql_error($wpdb));
+ $no_entrycat = mysql_error($wpdb);
} else {
- if ($debug) echo "Importing category associations...<br />\n";
+ if ($debug) echo "Importing category associations (WP 2.2 style)...<br />\n";
+ while ($a = mysql_fetch_assoc($res)) {
+ $data = array('entryid' => $assoc['entries'][$a['post_id']],
+ 'categoryid' => $assoc['categories'][$a['category_id']]);
+ serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+ }
+ if ($debug) echo "Imported category associations.<br />\n";
+ }
+
+ /* Entry/category (WP > 2.3 style)*/
+ $res = @$this->nativeQuery("SELECT rel.object_id AS post_id,
+ rel.term_taxonomy_id AS category_id
+ FROM {$this->data['prefix']}term_relationships AS rel;", $wpdb);
+ if (!$res && !$no_entrycat) {
+ $no_entrycat = mysql_error($wpdb);
+ } elseif ($res) {
+ $no_entrycat = false;
+ if ($debug) echo "Importing category associations (WP 2.3 style)...<br />\n";
while ($a = mysql_fetch_assoc($res)) {
$data = array('entryid' => $assoc['entries'][$a['post_id']],
'categoryid' => $assoc['categories'][$a['category_id']]);
if ($debug) echo "Imported category associations.<br />\n";
}
+ if ($no_entrycat) {
+ printf(COULDNT_SELECT_ENTRY_INFO, $no_entrycat);
+ }
+
/* Comments */
$res = @$this->nativeQuery("SELECT * FROM {$this->data['prefix']}comments;", $wpdb);
if (!$res) {
'subscribed'=> 'false',
'body' => $a['comment_content'],
'type' => 'NORMAL');
-
serendipity_db_insert('comments', $this->strtrRecursive($comment));
if ($comment['status'] == 'approved') {
$cid = serendipity_db_insert_id('comments', 'id');
- serendipity_approveComment($cid, $comment['entry_id'], true);
+ serendipity_approveComment($cid, $assoc['entries'][$a['comment_post_ID']], true);
}
}
if ($debug) echo "Imported comments.<br />\n";
$searchterms = explode($searchterms, ' ');
foreach($searchterms as $searchdx => $searchterm) {
$searchclass = "foundterm foundterm".$searchdx;
- $entry['body'] = preg_replace('/('.$searchterm.')/mi', '<span class="'.$searchclass.'">\1</span>', $entry['body']);
+ $entry['body'] = str_replace($searchterm, '<span class="'.$searchclass.'">' . $searchterm . '</span>', $entry['body']);
}
}
if (is_array($entries)) {
foreach ($entries as $key => $_entry) {
$entry = &$entries[$key];
+
+ if (isset($entry['entrytimestamp'])) {
+ $e_ts = $entry['entrytimestamp'];
+ } else {
+ $e_ts = $entry['timestamp'];
+ }
+
$entry['feed_id'] = (isset($entry['entryid']) && !empty($entry['entryid']) ? $entry['entryid'] : $entry['id']);
$entry['feed_guid'] = serendipity_rss_getguid($entry, $options['comments']);
- $entry['feed_entryLink'] = serendipity_archiveURL($entry['feed_id'], $entry['title'], 'baseURL', true, array('timestamp' => $entry['timestamp']));
+ $entry['feed_entryLink'] = serendipity_archiveURL($entry['feed_id'], $entry['title'], 'baseURL', true, array('timestamp' => $e_ts));
if ($options['comments'] == true) {
// Display username as part of the title for easier feed-readability
if ($entry['type'] == 'TRACKBACK' && !empty($entry['ctitle'])) {
$ext = '';
}
- $addData = array('from' => 'functions_entries:printEntries_rss');
+ $addData = array('from' => 'functions_entries:printEntries_rss','rss_options' => $options);
serendipity_plugin_api::hook_event('frontend_display', $entry, $addData);
+
// Do some relative -> absolute URI replacing magic. Replaces all HREF/SRC (<a>, <img>, ...) references to only the serendipitypath with the full baseURL URI
// garvin: Could impose some problems. Closely watch this one.
$entry['body'] = preg_replace('@(href|src)=("|\')(' . preg_quote($serendipity['serendipityHTTPPath']) . ')(.*)("|\')(.*)>@imsU', '\1=\2' . $serendipity['baseURL'] . '\4\2\6>', $entry['body']);
break;
case 'atom1.0':
- $entry_hook = 'frontend_display:atom-1.0:per_entry';
+ $entry_hook = 'frontend_display:atom-1.0:per_entry';
break;
}
$entry['per_entry_display_dat'] = $entry['display_dat'];
}
}
+
}