#!/usr/bin/env php -q 'DBhost', 'u' => 'DBuser', 'p' => 'DBpasswd', 'g' => 'geeklogDB', 'd' => 'drupalDB' ); $opts = getopt(implode(':', array_keys($args)).':'); foreach ($args as $k => $v) { if (empty($opts[$k])) { echo "Missing argument {$v}\n"; die("Usage: gl2drupal.php -h dbhost -u dbuser -p dbpasswd -g geeklogdb -d drupaldb\n"); } } $dbpw = $opts['p']; $dbhost = $opts['h'] . ":/Applications/MAMP/tmp/mysql/mysql.sock"; $dbuser = $opts['u']; $drupal_db = $opts['d']; $geeklog_db = $opts['g']; $gl_tbl_prefix = "gl_"; $db = mysql_connect($dbhost, $dbuser, $dbpw) or exit(mysql_error() . "\n"); // Add users mysql_query("DELETE FROM {$drupal_users}.users"); mysql_query("UPDATE {$drupal_db}.users SET `uid` = 0 WHERE `name` = ''"); $sql = << 1) EOS; query($sql, "Importing users"); // Reassign user roles (Groups) mysql_query("DELETE FROM {$drupal_db}.role WHERE `rid` > 2"); //$sql = "INSERT INTO drupal.role (name) (SELECT `grp_name` FROM geeklog.{$gl_tbl_prefix}groups)"; //query($sql, "Importing groups"); // Create "administrator" role query("INSERT INTO {$drupal_db}.role (rid, name) VALUES (3, 'administrator')", "Creating admin role"); // Grant all permissions to admin role $root_perms = "administer blocks, use PHP for block visibility, access comments, administer comments, post comments, post comments without approval, administer filters, administer menu, access content, administer content types, administer nodes, create page content, create story content, delete any page content, delete any story content, delete own page content, delete own story content, delete revisions, edit any page content, edit any story content, edit own page content, edit own story content, revert revisions, view revisions, access administration pages, access site reports, administer actions, administer files, administer site configuration, select different theme, administer taxonomy, access user profiles, administer permissions, administer users, change own username"; query("INSERT INTO {$drupal_db}.permission (rid, perm) VALUES (3, '{$root_perms}')"); /** * Assign Geeklog groups to corresponding Drupal roles * It would be possible to migrate groups verbatim, but we will focus on the most important ones: * Root (has full access to the site, ID 1) => administrator (ID 3) * "Logged-in Users" (ID 2) => "authenticated user" (ID 2) */ // Migrate all registered users $sql = << First comment in thread * 02/ -> Second comment in thread * 02.00/ -> First comment to the second comment * 02.00.00/ -> Second comment to the first comment of the second comment */ // Clear all old comments mysql_query("DELETE FROM {$drupal_db}.comments"); $sql =<< $v) { // $thread .= str_pad($k) // } // $thread = $index . str_repeat(".{$index}", $indent) . '/'; $thread = implode('.', $t) . '/'; $comment = mysql_real_escape_string($row['comment']); $subject = mysql_real_escape_string($row['title']); $insert = "INSERT INTO {$drupal_db}.comments (pid,nid,uid,subject,comment,hostname,timestamp,status,format,thread,name,mail) VALUES ({$row['pid']}, {$row['idx']}, {$row['uid']}, '$subject', '$comment', '{$row['ipaddress']}', {$row['date']}, 0, 1, '{$thread}', '{$row['username']}', '{$row['email']}')"; query($insert, "Inserting comment thread $thread"); echo "{$thread}\n"; } //exit(); // Remap Anonymous user $sql = "UPDATE {$drupal_db}.comments SET `uid` = 0 WHERE `uid` = 1"; query($sql, "Remapping Anonymous user"); /** * Update story comment counts * @todo * - last_comment_uid */ mysql_query("DELETE FROM {$drupal_db}.node_comment_statistics"); $sql =<< Forum > Post > Comment * "forum" = "term" * A Container is also a Forum (with term_hierarchy.parent_id = 0) * @NOTE The problem here is that forums and comments are in different * tables Geeklog whereas Drupal uses just term_data and node resulting in * ID collisions. * For containers, this is "solved" by adding 1000 to their IDs (as * it's pretty unlikely that someone will have over 1000 * forums (although the auto-increment might reach that)) */ mysql_query( "DELETE FROM {$drupal_db}.term_data" ); $sql =<< 0) EOS; query( $sql, "Importing forum comments" ); mysql_query( "ALTER TABLE {$drupal_db}.node DROP COLUMN tmp_forum_id" ); mysql_close( $db ); function query( $sql, $step = "Doing something" ) { mysql_query( $sql ); if (!empty( $step )) { echo result( $step ); } } function result( $action ) { $width = 100; $error = mysql_error(); $result = ($error) ? "Fail ($error)" : "[OK]"; $spaces = abs( $width - strlen( $action . $result )); $out = $action . str_repeat( " ", $spaces ); return "$out $result\n"; } /** * Flatten a modified pre-order traversal structure * into the Drupal form. * @param [string] $lft * @param (string) $rht * @param (string) $indent * @param (string) $current the current path * @return (string) a "node's" full path in Drupal notation */ function flatpot($lft, $rht, $indent, $current = '') { $sql = "SELECT lft, rht, indent FROM gl_comments WHERE lft < $lft AND rht > $rht ORDER BY lft ASC"; $result = mysql_query($sql); while ($row = mysql_fetch_assoc($result)) { $path = $current . $out .= flatpot($row['lft'], $row['rht'], $row['indent'], $path); } return $out; } /** * Generate vancode. * * Consists of a leading character indicating length, followed by N digits * with a numerical value in base 36. Vancodes can be sorted as strings * without messing up numerical order. * * It goes: * 00, 01, 02, ..., 0y, 0z, * 110, 111, ... , 1zy, 1zz, * 2100, 2101, ..., 2zzy, 2zzz, * 31000, 31001, ... */ function int2vancode($i = 0) { $num = base_convert((int)$i, 10, 36); $length = strlen($num); return chr($length + ord('0') - 1) . $num; } /** * Decode vancode back to an integer. */ function vancode2int($c = '00') { return base_convert(substr($c, 1), 36, 10); } ?>