From: garvinhicking Date: Thu, 6 Dec 2007 11:13:42 +0000 (+0000) Subject: Backport 1.3 features: X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=22090fb163ac193c4e4d50839f79bf4cd31075c9;p=s9y.git Backport 1.3 features: * Textile * Wrong timestamp * Highlighting search words * WPXRSS importer --- diff --git a/docs/NEWS b/docs/NEWS index 10fcd1d..da854ed 100644 --- a/docs/NEWS +++ b/docs/NEWS @@ -3,6 +3,18 @@ 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) diff --git a/include/admin/import.inc.php b/include/admin/import.inc.php index 17bd3cb..f0b4333 100644 --- a/include/admin/import.inc.php +++ b/include/admin/import.inc.php @@ -167,8 +167,31 @@ class Serendipity_Import { 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; } } diff --git a/include/admin/importers/generic.inc.php b/include/admin/importers/generic.inc.php index fe38f21..855b083 100644 --- a/include/admin/importers/generic.inc.php +++ b/include/admin/importers/generic.inc.php @@ -37,7 +37,13 @@ class Serendipity_Import_Generic extends Serendipity_Import { 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() { @@ -124,9 +130,196 @@ class Serendipity_Import_Generic extends Serendipity_Import { 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 "
\n"; + return false; + } + + $fContent = $req->getResponseBody(); + serendipity_request_end(); + echo strlen($fContent) . " Bytes
\n"; + + if (version_compare(PHP_VERSION, '5.0') === -1) { + printf(UNMET_REQUIREMENTS, 'PHP >= 5.0'); + echo "
\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 "
\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!
\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 "
\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.
\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']; @@ -146,4 +339,3 @@ class Serendipity_Import_Generic extends Serendipity_Import { return 'Serendipity_Import_Generic'; /* vim: set sts=4 ts=4 expandtab : */ -?> diff --git a/include/admin/importers/wordpress.inc.php b/include/admin/importers/wordpress.inc.php index 1d928d0..3c0cba5 100644 --- a/include/admin/importers/wordpress.inc.php +++ b/include/admin/importers/wordpress.inc.php @@ -143,14 +143,16 @@ class Serendipity_Import_WordPress extends Serendipity_Import { 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...
\n"; + if ($debug) echo "Importing categories (WP 2.2 style)...
\n"; // Get all the info we need for ($x=0 ; $x\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)...
\n"; + + // Get all the info we need + for ($x=0 ; $x $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.
\n"; + if ($debug) echo "Rebuilding category tree...
\n"; + serendipity_rebuildCategoryTree(); + if ($debug) echo "Rebuilt category tree.
\n"; + } + if ($no_cat) { + printf(COULDNT_SELECT_CATEGORY_INFO, $no_cat); + } /* Entries */ if (serendipity_db_bool($this->data['import_all'])) { @@ -241,12 +312,30 @@ class Serendipity_Import_WordPress extends Serendipity_Import { 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...
\n"; + if ($debug) echo "Importing category associations (WP 2.2 style)...
\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.
\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)...
\n"; while ($a = mysql_fetch_assoc($res)) { $data = array('entryid' => $assoc['entries'][$a['post_id']], 'categoryid' => $assoc['categories'][$a['category_id']]); @@ -255,6 +344,10 @@ class Serendipity_Import_WordPress extends Serendipity_Import { if ($debug) echo "Imported category associations.
\n"; } + if ($no_entrycat) { + printf(COULDNT_SELECT_ENTRY_INFO, $no_entrycat); + } + /* Comments */ $res = @$this->nativeQuery("SELECT * FROM {$this->data['prefix']}comments;", $wpdb); if (!$res) { @@ -274,11 +367,10 @@ class Serendipity_Import_WordPress extends Serendipity_Import { '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.
\n"; diff --git a/include/functions_entries.inc.php b/include/functions_entries.inc.php index 673f5c1..2e629ef 100644 --- a/include/functions_entries.inc.php +++ b/include/functions_entries.inc.php @@ -958,7 +958,7 @@ function serendipity_printEntries($entries, $extended = 0, $preview = false, $sm $searchterms = explode($searchterms, ' '); foreach($searchterms as $searchdx => $searchterm) { $searchclass = "foundterm foundterm".$searchdx; - $entry['body'] = preg_replace('/('.$searchterm.')/mi', '\1', $entry['body']); + $entry['body'] = str_replace($searchterm, '' . $searchterm . '', $entry['body']); } } diff --git a/include/functions_rss.inc.php b/include/functions_rss.inc.php index fdbcc84..8e5a580 100644 --- a/include/functions_rss.inc.php +++ b/include/functions_rss.inc.php @@ -40,9 +40,16 @@ function serendipity_printEntries_rss(&$entries, $version, $comments = false, $f 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'])) { @@ -64,8 +71,9 @@ function serendipity_printEntries_rss(&$entries, $version, $comments = false, $f $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 (, , ...) 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']); @@ -135,7 +143,7 @@ function serendipity_printEntries_rss(&$entries, $version, $comments = false, $f break; case 'atom1.0': - $entry_hook = 'frontend_display:atom-1.0:per_entry'; + $entry_hook = 'frontend_display:atom-1.0:per_entry'; break; } @@ -143,4 +151,5 @@ function serendipity_printEntries_rss(&$entries, $version, $comments = false, $f $entry['per_entry_display_dat'] = $entry['display_dat']; } } + }