コード例 #1
0
ファイル: class.vanilla1.php プロジェクト: vjt/VanillaPorter
 /**
  * Forum-specific export format
  * @todo Project file size / export time and possibly break into multiple files
  * @param ExportModel $Ex
  * 
  */
 protected function ForumExport($Ex)
 {
     // Get the characterset for the comments.
     $CharacterSet = $Ex->GetCharacterSet('Comment');
     if ($CharacterSet) {
         $Ex->CharacterSet = $CharacterSet;
     }
     // Begin
     $Ex->BeginExport('', 'Vanilla 1.*');
     // Users
     $User_Map = array('UserID' => 'UserID', 'Name' => 'Name', 'Password' => 'Password', 'Email' => 'Email', 'Icon' => 'Photo', 'CountComments' => 'CountComments', 'Discovery' => 'DiscoveryText');
     $Ex->ExportTable('User', "SELECT * FROM :_User", $User_Map);
     // ":_" will be replaced by database prefix
     // Roles
     // Since the zero role is a valid role in Vanilla 1 then we'll have to reassign it.
     $R = $Ex->Query('select max(RoleID) as RoleID from :_Role');
     $ZeroRoleID = 0;
     if (is_resource($R)) {
         while (($Row = @mysql_fetch_assoc($R)) !== false) {
             $ZeroRoleID = $Row['RoleID'];
         }
     }
     $ZeroRoleID++;
     /*
        'RoleID' => 'int', 
        'Name' => 'varchar(100)', 
        'Description' => 'varchar(200)'
     */
     $Role_Map = array('RoleID' => 'RoleID', 'Name' => 'Name', 'Description' => 'Description');
     $Ex->ExportTable('Role', "select RoleID, Name, Description from :_Role union all select {$ZeroRoleID}, 'Applicant', 'Created by the Vanilla Porter'", $Role_Map);
     // UserRoles
     /*
        'UserID' => 'int', 
        'RoleID' => 'int'
     */
     $UserRole_Map = array('UserID' => 'UserID', 'RoleID' => 'RoleID');
     $Ex->ExportTable('UserRole', "select UserID, case RoleID when 0 then {$ZeroRoleID} else RoleID end as RoleID from :_User", $UserRole_Map);
     // Categories
     /*
               'CategoryID' => 'int', 
               'Name' => 'varchar(30)', 
               'Description' => 'varchar(250)', 
               'ParentCategoryID' => 'int', 
               'DateInserted' => 'datetime', 
               'InsertUserID' => 'int', 
               'DateUpdated' => 'datetime', 
               'UpdateUserID' => 'int'
     */
     $Category_Map = array('CategoryID' => 'CategoryID', 'Name' => 'Name', 'Description' => 'Description');
     $Ex->ExportTable('Category', "select CategoryID, Name, Description from :_Category", $Category_Map);
     // Discussions
     /*
        'DiscussionID' => 'int', 
        'Name' => 'varchar(100)', 
        'CategoryID' => 'int', 
        'Body' => 'text', 
        'Format' => 'varchar(20)', 
        'DateInserted' => 'datetime', 
        'InsertUserID' => 'int', 
        'DateUpdated' => 'datetime', 
        'UpdateUserID' => 'int', 
        'Score' => 'float', 
        'Announce' => 'tinyint', 
        'Closed' => 'tinyint'
     */
     $Discussion_Map = array('DiscussionID' => 'DiscussionID', 'Name' => 'Name', 'CategoryID' => 'CategoryID', 'DateCreated' => 'DateInserted', 'DateCreated2' => 'DateUpdated', 'AuthUserID' => 'InsertUserID', 'DateLastActive' => 'DateLastComment', 'AuthUserID2' => 'UpdateUserID', 'Closed' => 'Closed', 'Sticky' => 'Announce', 'CountComments' => 'CountComments', 'Sink' => 'Sink', 'LastUserID' => 'LastCommentUserID');
     $Ex->ExportTable('Discussion', "SELECT d.*,\n            d.LastUserID as LastCommentUserID,\n            d.DateCreated as DateCreated2, d.AuthUserID as AuthUserID2\n         FROM :_Discussion d\n         WHERE coalesce(d.WhisperUserID, 0) = 0 and d.Active = 1", $Discussion_Map);
     // Comments
     /*
        'CommentID' => 'int', 
        'DiscussionID' => 'int', 
        'DateInserted' => 'datetime', 
        'InsertUserID' => 'int', 
        'DateUpdated' => 'datetime', 
        'UpdateUserID' => 'int', 
        'Format' => 'varchar(20)', 
        'Body' => 'text', 
        'Score' => 'float'
     */
     $Comment_Map = array('CommentID' => 'CommentID', 'DiscussionID' => 'DiscussionID', 'AuthUserID' => 'InsertUserID', 'DateCreated' => 'DateInserted', 'EditUserID' => 'UpdateUserID', 'DateEdited' => 'DateUpdated', 'Body' => 'Body', 'FormatType' => 'Format');
     $Ex->ExportTable('Comment', "\n         SELECT \n            c.*\n         FROM :_Comment c\n         JOIN :_Discussion d\n            ON c.DiscussionID = d.DiscussionID\n         WHERE coalesce(d.WhisperUserID, 0) = 0\n            AND coalesce(c.WhisperUserID, 0) = 0", $Comment_Map);
     $Ex->ExportTable('UserDiscussion', "\n         SELECT\n            w.UserID,\n            w.DiscussionID,\n            w.CountComments,\n            w.LastViewed as DateLastViewed,\n            case when b.UserID is not null then 1 else 0 end AS Bookmarked\n         FROM :_UserDiscussionWatch w\n         LEFT JOIN :_UserBookmark b\n            ON w.DiscussionID = b.DiscussionID AND w.UserID = b.UserID");
     // Conversations
     // Create a mapping table for conversations.
     // This cannot be a temporary table because of some of the union selects it is used in below.
     $Ex->Query("create table :_V1Conversation (ConversationID int auto_increment primary key, DiscussionID int, UserID1 int, UserID2 int, DateCreated datetime, EditUserID int, DateEdited datetime)");
     $Ex->Query("insert :_V1Conversation (DiscussionID, UserID1, UserID2, DateCreated, EditUserID, DateEdited)\n         select\n           DiscussionID,\n           AuthUserID as UserID1,\n           WhisperUserID as UserID2,\n           min(DateCreated),\n           max(EditUserID),\n           max(DateEdited)\n         from :_Comment\n         where coalesce(WhisperUserID, 0) <> 0\n         group by DiscussionID, AuthUserID, WhisperUserID\n\n         union\n\n         select\n           DiscussionID,\n           AuthUserID as UserID1,\n           WhisperUserID as UserID2,\n           DateCreated,\n           WhisperFromLastUserID,\n           DateLastWhisper\n         from :_Discussion\n         where coalesce(WhisperUserID, 0) <> 0");
     // Delete redundant conversations.
     $Ex->Query("create index ix_V1UserID1 on :_V1Conversation (DiscussionID, UserID1)");
     // for speed
     $Ex->Query("delete t.*\n         from :_V1Conversation t\n         inner join :_Comment c\n           on c.DiscussionID = t.DiscussionID\n             and c.AuthUserID = t.UserID2\n             and c.WhisperUserID = t.UserID1\n             and c.AuthUserID < c.WhisperUserID");
     $Conversation_Map = array('UserID1' => 'InsertUserID', 'DateCreated' => 'DateInserted', 'EditUserID' => 'UpdateUserID', 'DateEdited' => 'DateUpdated');
     $Ex->ExportTable('Conversation', "select * from :_V1Conversation", $Conversation_Map);
     // ConversationMessage
     /*
        'MessageID' => 'int', 
        'ConversationID' => 'int', 
        'Body' => 'text', 
        'InsertUserID' => 'int', 
        'DateInserted' => 'datetime'
     */
     $ConversationMessage_Map = array('CommentID' => 'MessageID', 'DiscussionID' => 'ConversationID', 'Body' => 'Body', 'AuthUserID' => 'InsertUserID', 'DateCreated' => 'DateInserted');
     $Ex->ExportTable('ConversationMessage', "\n         select c.CommentID, t.ConversationID, c.AuthUserID, c.DateCreated, c.Body\n         from :_Comment c\n         join :_V1Conversation t\n           on t.DiscussionID = c.DiscussionID\n             and c.WhisperUserID in (t.UserID1, t.UserID2)\n             and c.AuthUserID in (t.UserID1, t.UserID2)\n         where c.WhisperUserID > 0\n\n         union\n\n         select c.CommentID, t.ConversationID, c.AuthUserID, c.DateCreated, c.Body\n         from :_Comment c\n         join :_Discussion d\n          on c.DiscussionID = d.DiscussionID\n         join :_V1Conversation t\n           on t.DiscussionID = d.DiscussionID\n             and d.WhisperUserID in (t.UserID1, t.UserID2)\n             and d.AuthUserID in (t.UserID1, t.UserID2)\n         where d.WhisperUserID > 0", $ConversationMessage_Map);
     // UserConversation
     /*
        'UserID' => 'int', 
        'ConversationID' => 'int', 
        'LastMessageID' => 'int'
     */
     $UserConversation_Map = array('UserID' => 'UserID', 'ConversationID' => 'ConversationID');
     $Ex->ExportTable('UserConversation', "select UserID1 as UserID, ConversationID\n         from :_V1Conversation\n\n         union\n\n         select UserID2 as UserID, ConversationID\n         from :_V1Conversation", $UserConversation_Map);
     $Ex->Query("drop table :_V1Conversation");
     // Media
     if ($Ex->Exists('Attachment')) {
         $Media_Map = array('AttachmentID' => 'MediaID', 'Name' => 'Name', 'MimeType' => 'Type', 'Size' => 'Size', 'Path' => array('Column' => 'Path', 'Filter' => array($this, 'StripMediaPath')), 'UserID' => 'InsertUserID', 'DateCreated' => 'DateInserted', 'CommentID' => 'ForeignID');
         $Ex->ExportTable('Media', "select a.*, 'local' as StorageMethod, 'comment' as ForeignTable from :_Attachment a", $Media_Map);
     }
     // End
     $Ex->EndExport();
 }
コード例 #2
0
    /**
     * Forum-specific export format.
     * @param ExportModel $Ex
     */
    protected function ForumExport($Ex)
    {
        // Begin
        $Ex->BeginExport('', 'bbPress 1.*', array('HashMethod' => 'Vanilla'));
        // Users
        $User_Map = array('ID' => 'UserID', 'user_nicename' => 'Name', 'user_pass' => 'Password', 'user_email' => 'Email', 'user_registered' => 'DateInserted');
        $Ex->ExportTable('User', "select * from :_users", $User_Map);
        // ":_" will be replace by database prefix
        // Roles
        $Ex->ExportTable('Role', "select 1 as RoleID, 'Guest' as Name\n         union select 2, 'Key Master'\n         union select 3, 'Administrator'\n         union select 4, 'Moderator'\n         union select 5, 'Member'\n         union select 6, 'Inactive'\n         union select 7, 'Blocked'");
        // UserRoles
        $UserRole_Map = array('user_id' => 'UserID');
        $Ex->ExportTable('UserRole', "select distinct\n           user_id,\n           case when locate('keymaster', meta_value) <> 0 then 2\n           when locate('administrator', meta_value) <> 0 then 3\n           when locate('moderator', meta_value) <> 0 then 4\n           when locate('member', meta_value) <> 0 then 5\n           when locate('inactive', meta_value) <> 0 then 6\n           when locate('blocked', meta_value) <> 0 then 7\n           else 1 end as RoleID\n         from :_usermeta\n         where meta_key = 'bb_capabilities'", $UserRole_Map);
        // Categories
        $Category_Map = array('forum_id' => 'CategoryID', 'forum_name' => 'Name', 'forum_desc' => 'Description', 'form_slug' => 'UrlCode', 'left_order' => 'Sort');
        $Ex->ExportTable('Category', "select *,\n         nullif(forum_parent,0) as ParentCategoryID\n         from :_forums", $Category_Map);
        // Discussions
        $Discussion_Map = array('topic_id' => 'DiscussionID', 'forum_id' => 'CategoryID', 'topic_poster' => 'InsertUserID', 'topic_title' => 'Name', 'Format' => 'Format', 'topic_start_time' => 'DateInserted', 'topic_sticky' => 'Announce');
        $Ex->ExportTable('Discussion', "select t.*,\n\t\t\t\t'Html' as Format,\n            case t.topic_open when 0 then 1 else 0 end as Closed\n         from :_topics t", $Discussion_Map);
        // Comments
        $Comment_Map = array('post_id' => 'CommentID', 'topic_id' => 'DiscussionID', 'post_text' => 'Body', 'Format' => 'Format', 'Body' => array('Column' => 'Body', 'Filter' => 'bbPressTrim'), 'poster_id' => 'InsertUserID', 'post_time' => 'DateInserted');
        $Ex->ExportTable('Comment', "select p.*,\n\t\t\t\t'Html' as Format\n         from :_posts p", $Comment_Map);
        // Conversations.
        // The export is different depending on the table layout.
        $PM = $Ex->Exists('bbpm', array('ID', 'pm_title', 'pm_from', 'pm_to', 'pm_text', 'sent_on', 'pm_thread'));
        $ConversationVersion = '';
        if ($PM === TRUE) {
            // This is from an old version of the plugin.
            $ConversationVersion = 'old';
        } elseif (is_array($PM) && count(array_intersect(array('ID', 'pm_from', 'pm_text', 'sent_on', 'pm_thread'), $PM)) == 0) {
            // This is from a newer version of the plugin.
            $ConversationVersion = 'new';
        }
        if ($ConversationVersion) {
            // Conversation.
            $Conv_Map = array('pm_thread' => 'ConversationID', 'pm_from' => 'InsertUserID');
            $Ex->ExportTable('Conversation', "select *, from_unixtime(sent_on) as DateInserted\n            from :_bbpm\n            where thread_depth = 0", $Conv_Map);
            // ConversationMessage.
            $ConvMessage_Map = array('ID' => 'MessageID', 'pm_thread' => 'ConversationID', 'pm_from' => 'InsertUserID', 'pm_text' => array('Column' => 'Body', 'Filter' => 'bbPressTrim'));
            $Ex->ExportTable('ConversationMessage', 'select *, from_unixtime(sent_on) as DateInserted
            from :_bbpm', $ConvMessage_Map);
            // UserConversation.
            $Ex->Query("create temporary table bbpmto (UserID int, ConversationID int)");
            if ($ConversationVersion == 'new') {
                $To = $Ex->Query("select object_id, meta_value from bb_meta where object_type = 'bbpm_thread' and meta_key = 'to'", TRUE);
                if (is_resource($To)) {
                    while (($Row = @mysql_fetch_assoc($To)) !== false) {
                        $Thread = $Row['object_id'];
                        $Tos = explode(',', trim($Row['meta_value'], ','));
                        $ToIns = '';
                        foreach ($Tos as $ToID) {
                            $ToIns .= "({$ToID},{$Thread}),";
                        }
                        $ToIns = trim($ToIns, ',');
                        $Ex->Query("insert bbpmto (UserID, ConversationID) values {$ToIns}", TRUE);
                    }
                    mysql_free_result($To);
                    $Ex->ExportTable('UserConversation', 'select * from bbpmto');
                }
            } else {
                $ConUser_Map = array('pm_thread' => 'ConversationID', 'pm_from' => 'UserID');
                $Ex->ExportTable('UserConversation', 'select distinct
                 pm_thread,
                 pm_from,
                 del_sender as Deleted
               from bb_bbpm

               union

               select distinct
                 pm_thread,
                 pm_to,
                 del_reciever
               from bb_bbpm', $ConUser_Map);
            }
        }
        // End
        $Ex->EndExport();
    }
コード例 #3
0
ファイル: vanilla2export.php プロジェクト: Nordic-T/Nordic-T
 /**
  *
  * @param ExportModel $Ex
  */
 public function ForumExport($Ex)
 {
     // Determine the character set
     $CharacterSet = $Ex->GetCharacterSet('nodes');
     if ($CharacterSet) {
         $Ex->CharacterSet = $CharacterSet;
     }
     $Ex->BeginExport('', 'vBulletin 5 Connect');
     $this->ExportBlobs($this->Param('files'), $this->Param('avatars'));
     if ($this->Param('noexport')) {
         $Ex->Comment('Skipping the export.');
         $Ex->EndExport();
         return;
     }
     $cdn = $this->Param('cdn', '');
     // Grab all of the ranks.
     $Ranks = $Ex->Get("select * from :_usertitle order by minposts desc", 'usertitleid');
     // Users
     $User_Map = array('userid' => 'UserID', 'username' => 'Name', 'password2' => 'Password', 'email' => 'Email', 'referrerid' => 'InviteUserID', 'timezoneoffset' => 'HourOffset', 'ipaddress' => 'LastIPAddress', 'ipaddress2' => 'InsertIPAddress', 'usertitle' => 'Title', 'posts' => array('Column' => 'RankID', 'Filter' => function ($Value) use($Ranks) {
         // Look  up the posts in the ranks table.
         foreach ($Ranks as $RankID => $Row) {
             if ($Value >= $Row['minposts']) {
                 return $RankID;
             }
         }
         return null;
     }));
     // Use file avatar or the result of our blob export?
     if ($this->GetConfig('usefileavatar')) {
         $User_Map['filephoto'] = 'Photo';
     } else {
         $User_Map['customphoto'] = 'Photo';
     }
     // vBulletin 5.1 changes the hash to crypt(md5(password), hash).
     // Switches from password & salt to token (and scheme & secret).
     // The scheme appears to be crypt()'s default and secret looks uselessly redundant.
     if ($Ex->Exists('user', 'token') !== true) {
         $PasswordSQL = "concat(`password`, salt) as password2, 'vbulletin' as HashMethod,";
     } else {
         // vB 5.1 already concats the salt to the password as token, BUT ADDS A SPACE OF COURSE.
         $PasswordSQL = "replace(token, ' ', '') as password2,\n         case when scheme = 'legacy' then 'vbulletin' else 'vbulletin5' end as HashMethod,";
     }
     $Ex->ExportTable('User', "select u.*,\n            ipaddress as ipaddress2,\n            {$PasswordSQL}\n            DATE_FORMAT(birthday_search,GET_FORMAT(DATE,'ISO')) as DateOfBirth,\n            FROM_UNIXTIME(joindate) as DateFirstVisit,\n            FROM_UNIXTIME(lastvisit) as DateLastActive,\n            FROM_UNIXTIME(joindate) as DateInserted,\n            FROM_UNIXTIME(lastactivity) as DateUpdated,\n            case when avatarrevision > 0 then concat('{$cdn}', 'userpics/avatar', u.userid, '_', avatarrevision, '.gif')\n                 when av.avatarpath is not null then av.avatarpath\n                 else null\n                 end as filephoto,\n            {$this->AvatarSelect},\n            case when ub.userid is not null then 1 else 0 end as Banned\n         from :_user u\n         left join :_customavatar a\n            on u.userid = a.userid\n         left join :_avatar av\n            on u.avatarid = av.avatarid\n         left join :_userban ub\n              on u.userid = ub.userid and ub.liftdate <= now() ", $User_Map);
     // ":_" will be replace by database prefix
     //ipdata - contains all IP records for user actions: view,visit,register,logon,logoff
     // Roles
     $Role_Map = array('usergroupid' => 'RoleID', 'title' => 'Name', 'description' => 'Description');
     $Ex->ExportTable('Role', 'select * from :_usergroup', $Role_Map);
     // UserRoles
     $UserRole_Map = array('userid' => 'UserID', 'usergroupid' => 'RoleID');
     $Ex->Query("CREATE TEMPORARY TABLE VbulletinRoles (userid INT UNSIGNED NOT NULL, usergroupid INT UNSIGNED NOT NULL)");
     # Put primary groups into tmp table
     $Ex->Query("insert into VbulletinRoles (userid, usergroupid) select userid, usergroupid from :_user");
     # Put stupid CSV column into tmp table
     $SecondaryRoles = $Ex->Query("select userid, usergroupid, membergroupids from :_user", true);
     if (is_resource($SecondaryRoles)) {
         while (($Row = @mysql_fetch_assoc($SecondaryRoles)) !== false) {
             if ($Row['membergroupids'] != '') {
                 $Groups = explode(',', $Row['membergroupids']);
                 foreach ($Groups as $GroupID) {
                     $Ex->Query("insert into VbulletinRoles (userid, usergroupid) values({$Row['userid']},{$GroupID})", true);
                 }
             }
         }
     }
     # Export from our tmp table and drop
     $Ex->ExportTable('UserRole', 'select distinct userid, usergroupid from VbulletinRoles', $UserRole_Map);
     $Ex->Query("DROP TABLE IF EXISTS VbulletinRoles");
     // Permissions.
     $Permissions_Map = array('usergroupid' => 'RoleID', 'title' => array('Column' => 'Garden.SignIn.Allow', 'Filter' => array($this, 'SignInPermission')), 'genericpermissions' => array('Column' => 'GenericPermissions', 'type' => 'int'), 'forumpermissions' => array('Column' => 'ForumPermissions', 'type' => 'int'));
     $this->AddPermissionColumns(self::$Permissions, $Permissions_Map);
     $Ex->ExportTable('Permission', 'select * from :_usergroup', $Permissions_Map);
     // UserMeta
     /*$Ex->Query("CREATE TEMPORARY TABLE VbulletinUserMeta (`UserID` INT NOT NULL ,`Name` VARCHAR( 255 ) NOT NULL ,`Value` text NOT NULL)");
       # Standard vB user data
       $UserFields = array('usertitle' => 'Title', 'homepage' => 'Website', 'skype' => 'Skype', 'styleid' => 'StyleID');
       foreach($UserFields as $Field => $InsertAs)
          $Ex->Query("insert into VbulletinUserMeta (UserID, Name, Value) select userid, 'Profile.$InsertAs', $Field from :_user where $Field != ''");
       # Dynamic vB user data (userfield)
       $ProfileFields = $Ex->Query("select varname, text from :_phrase where product='vbulletin' and fieldname='cprofilefield' and varname like 'field%_title'");
       if (is_resource($ProfileFields)) {
          $ProfileQueries = array();
          while ($Field = @mysql_fetch_assoc($ProfileFields)) {
             $Column = str_replace('_title', '', $Field['varname']);
             $Name = preg_replace('/[^a-zA-Z0-9_-\s]/', '', $Field['text']);
             $ProfileQueries[] = "insert into VbulletinUserMeta (UserID, Name, Value)
                select userid, 'Profile.".$Name."', ".$Column." from :_userfield where ".$Column." != ''";
          }
          foreach ($ProfileQueries as $Query) {
             $Ex->Query($Query);
          }
       }*/
     // Ranks
     $Rank_Map = array('usertitleid' => 'RankID', 'title' => 'Name', 'title2' => 'Label', 'minposts' => array('Column' => 'Attributes', 'Filter' => function ($Value) {
         $Result = array('Criteria' => array('CountPosts' => $Value));
         return serialize($Result);
     }), 'level' => array('Column' => 'Level', 'Filter' => function ($Value) {
         static $Level = 1;
         return $Level++;
     }));
     $Ex->ExportTable('Rank', "\n         select ut.*, ut.title as title2, 0 as level\n         from :_usertitle ut\n         order by ut.minposts", $Rank_Map);
     /// Signatures
     // usertextfields.signature
     // Ignore
     // usertextfields.ignorelist
     /// Notes
     /// Warnings
     /// Activity (Wall)
     // Category.
     $Channels = array();
     $CategoryIDs = array();
     $HomeID = 0;
     $PrivateMessagesID = 0;
     // Filter Channels down to Forum tree
     $ChannelResult = $Ex->Query("select n.* from :_node n\n         left join :_contenttype c on n.contenttypeid = c.contenttypeid\n         where c.class = 'Channel'");
     while ($Channel = mysql_fetch_array($ChannelResult)) {
         $Channels[$Channel['nodeid']] = $Channel;
         if ($Channel['title'] == 'Forum') {
             $HomeID = $Channel['nodeid'];
         }
         if ($Channel['title'] == 'Private Messages') {
             $PrivateMessagesID = $Channel['nodeid'];
         }
     }
     if (!$HomeID) {
         exit("Missing node 'Forum'");
     }
     // Go thru the category list 6 times to build a (up to) 6-deep hierarchy
     $CategoryIDs[] = $HomeID;
     for ($i = 0; $i < 6; $i++) {
         foreach ($Channels as $Channel) {
             if (in_array($Channel['nodeid'], $CategoryIDs)) {
                 continue;
             }
             if (in_array($Channel['parentid'], $CategoryIDs)) {
                 $CategoryIDs[] = $Channel['nodeid'];
             }
         }
     }
     // Drop 'Forum' from the tree
     if (($key = array_search($HomeID, $CategoryIDs)) !== false) {
         unset($CategoryIDs[$key]);
     }
     $Category_Map = array('nodeid' => 'CategoryID', 'title' => 'Name', 'description' => 'Description', 'userid' => 'InsertUserID', 'parentid' => 'ParentCategoryID', 'urlident' => 'UrlCode', 'displayorder' => array('Column' => 'Sort', 'Type' => 'int'), 'lastcontentid' => 'LastDiscussionID', 'textcount' => 'CountComments', 'totalcount' => 'CountDiscussions');
     // Categories are Channels that were found in the Forum tree
     // If parent was 'Forum' set the parent to Root instead (-1)
     $Ex->ExportTable('Category', "select n.*,\n         FROM_UNIXTIME(publishdate) as DateInserted,\n         if(parentid={$HomeID},-1,parentid) as parentid\n      from :_node n\n      where nodeid in (" . implode(',', $CategoryIDs) . ")\n      ", $Category_Map);
     /// Permission
     //permission - nodeid,(user)groupid, and it gets worse from there.
     // Discussion.
     $Discussion_Map = array('nodeid' => 'DiscussionID', 'title' => 'Name', 'userid' => 'InsertUserID', 'rawtext' => 'Body', 'parentid' => 'CategoryID', 'lastcontentid' => 'LastCommentID', 'lastauthorid' => 'LastCommentUserID');
     $Ex->ExportTable('Discussion', "select n.*,\n         t.rawtext,\n         'BBCode' as Format,\n         FROM_UNIXTIME(publishdate) as DateInserted,\n         v.count as CountViews,\n         convert(ABS(open-1),char(1)) as Closed,\n         if(convert(sticky,char(1))>0,2,0) as Announce\n      from :_node n\n         left join :_contenttype c on n.contenttypeid = c.contenttypeid\n         left join :_nodeview v on v.nodeid = n.nodeid\n         left join :_text t on t.nodeid = n.nodeid\n      where c.class = 'Text'\n         and n.showpublished = 1\n         and parentid in (" . implode(',', $CategoryIDs) . ")\n      ", $Discussion_Map);
     // UserDiscussion
     $UserDiscussion_Map = array('discussionid' => 'DiscussionID', 'userid' => 'InsertUserID');
     // Should be able to inner join `discussionread` for DateLastViewed
     // but it's blank in my sample data so I don't trust it.
     $Ex->ExportTable('UserDiscussion', "select s.*,\n         1 as Bookmarked,\n         NOW() as DateLastViewed\n      from :_subscribediscussion s\n      ", $UserDiscussion_Map);
     // Comment.
     $Comment_Map = array('nodeid' => 'CommentID', 'rawtext' => 'Body', 'userid' => 'InsertUserID', 'parentid' => 'DiscussionID');
     $Ex->ExportTable('Comment', "select n.*,\n         t.rawtext,\n         'BBCode' as Format,\n         FROM_UNIXTIME(publishdate) as DateInserted\n      from :_node n\n         left join :_contenttype c on n.contenttypeid = c.contenttypeid\n         left join :_text t on t.nodeid = n.nodeid\n      where c.class = 'Text'\n         and n.showpublished = 1\n         and parentid not in (" . implode(',', $CategoryIDs) . ")\n      ", $Comment_Map);
     /// Drafts
     // autosavetext table
     /// Poll
     // class='Poll'
     // Media
     $Media_Map = array('nodeid' => 'MediaID', 'filename' => 'Name', 'extension' => array('Column' => 'Type', 'Filter' => array($this, 'BuildMimeType')), 'Path2' => array('Column' => 'Path', 'Filter' => array($this, 'BuildMediaPath')), 'ThumbPath2' => array('Column' => 'ThumbPath', 'Filter' => array($this, 'BuildMediaPath')), 'width' => 'ImageWidth', 'height' => 'ImageHeight', 'filesize' => 'Size');
     $Ex->ExportTable('Media', "select a.*,\n         filename as Path2,\n         filename as ThumbPath2,\n         FROM_UNIXTIME(f.dateline) as DateInserted,\n         f.userid as userid,\n         f.userid as InsertUserID,\n         if (f.width,f.width,1) as width,\n         if (f.height,f.height,1) as height,\n         n.parentid as ForeignID,\n         f.extension,\n         f.filesize,\n         'local' as StorageMethod,\n         if(n2.parentid in (" . implode(',', $CategoryIDs) . "),'discussion','comment') as ForeignTable\n      from :_attach a\n         left join :_node n on n.nodeid = a.nodeid\n         left join :_filedata f on f.filedataid = a.filedataid\n         left join :_node n2 on n.parentid = n2.nodeid\n      where a.visible = 1\n      ", $Media_Map);
     // left join :_contenttype c on n.contenttypeid = c.contenttypeid
     // Conversations.
     $Conversation_Map = array('nodeid' => 'ConversationID', 'userid' => 'InsertUserID', 'totalcount' => 'CountMessages', 'title' => 'Subject');
     $Ex->ExportTable('Conversation', "select n.*,\n            n.nodeid as FirstMessageID,\n            FROM_UNIXTIME(n.publishdate) as DateInserted\n          from :_node n\n            left join :_text t on t.nodeid = n.nodeid\n          where parentid = {$PrivateMessagesID}\n            and t.rawtext <> ''", $Conversation_Map);
     // Conversation Messages.
     $ConversationMessage_Map = array('nodeid' => 'MessageID', 'rawtext' => 'Body', 'userid' => 'InsertUserID');
     $Ex->ExportTable('ConversationMessage', "select n.*,\n            t.rawtext,\n            'BBCode' as Format,\n            if(n.parentid<>{$PrivateMessagesID},n.parentid,n.nodeid) as ConversationID,\n            FROM_UNIXTIME(n.publishdate) as DateInserted\n          from :_node n\n            left join :_contenttype c on n.contenttypeid = c.contenttypeid\n            left join :_text t on t.nodeid = n.nodeid\n          where c.class = 'PrivateMessage'\n            and t.rawtext <> ''", $ConversationMessage_Map);
     // User Conversation.
     $UserConversation_Map = array('userid' => 'UserID', 'nodeid' => 'ConversationID', 'deleted' => 'Deleted');
     // would be nicer to do an intermediary table to sum s.msgread for uc.CountReadMessages
     $Ex->ExportTable('UserConversation', "select s.*\n          from :_sentto s\n          ;", $UserConversation_Map);
     /// Groups
     // class='SocialGroup'
     // class='SocialGroupDiscussion'
     // class='SocialGroupMessage'
     $Ex->EndExport();
 }