示例#1
0
 /**
  * Export each table one at a time.
  *
  * @param ExportModel $ex
  */
 protected function forumExport($ex)
 {
     // Allow limited export of 1 category via ?forumid=ID
     $forumID = $this->param('forumid');
     if ($forumID) {
         $forumWhere = ' and t.forumid ' . (strpos($forumID, ', ') === false ? "= {$forumID}" : "in ({$forumID})");
     } else {
         $forumWhere = '';
     }
     $characterSet = $ex->getCharacterSet('post');
     if ($characterSet) {
         $ex->characterSet = $characterSet;
     }
     // Begin
     $ex->beginExport('', 'vBulletin 3.* and 4.*');
     $this->exportBlobs($this->param('files'), $this->param('avatars'));
     if ($this->param('noexport')) {
         $ex->comment('Skipping the export.');
         $ex->endExport();
         return;
     }
     // Check to see if there is a max date.
     $minDate = $this->param('mindate');
     if ($minDate) {
         $minDate = strtotime($minDate);
         $ex->comment("Min topic date ({$minDate}): " . date('c', $minDate));
     }
     $now = time();
     $cdn = $this->param('cdn', '');
     // Grab all of the ranks.
     $ranks = $ex->get("select * from :_usertitle order by minposts desc", 'usertitleid');
     // Users
     $user_Map = array('usertitle' => array('Column' => 'Title', 'Filter' => function ($value) {
         return trim(strip_tags(str_replace(' ', ' ', $value)));
     }), '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';
     }
     $ex->exportTable('User', "\n            select\n                u.userid as UserID,\n                u.username as Name,\n                u.email as Email,\n                u.referrerid as InviteUserID,\n                u.timezoneoffset as HourOffset,\n                u.timezoneoffset as HourOffset,\n                u.ipaddress as LastIPAddress,\n                u.ipaddress as InsertIPAddress,\n                u.usertitle,\n                u.posts,\n                concat(`password`, salt) as Password,\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                'vbulletin' as HashMethod\n            from :_user u\n                left join :_customavatar a on u.userid = a.userid\n                left join :_avatar av on u.avatarid = av.avatarid\n                left join :_userban ub on u.userid = ub.userid and ub.liftdate <= now()\n        ", $user_Map);
     // ":_" will be replace by database prefix
     // 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("drop table if exists VbulletinRoles");
     $ex->query("create 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");
     if (is_resource($secondaryRoles)) {
         while (($row = @mysql_fetch_assoc($secondaryRoles)) !== false) {
             if ($row['membergroupids'] != '') {
                 $groups = explode(',', $row['membergroupids']);
                 foreach ($groups as $groupID) {
                     if (!$groupID) {
                         continue;
                     }
                     $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);
     $ex->query("drop table if exists VbulletinUserMeta");
     // UserMeta
     $ex->query("\n            create table VbulletinUserMeta(\n                `UserID` int not null,\n                `Name` varchar(255) not null,\n                `Value` text not null\n            );\n        ");
     # Standard vB user data
     $userFields = array('usertitle' => 'Title', 'homepage' => 'Website', 'styleid' => 'StyleID');
     if ($ex->exists('user', array('skype')) === true) {
         $userFields['skype'] = 'Skype';
     }
     foreach ($userFields as $field => $insertAs) {
         $ex->query("\n                insert into VbulletinUserMeta (UserID, Name, Value)\n                    select\n                        userid,\n                        'Profile.{$insertAs}',\n                        {$field}\n                    from :_user where {$field} != '' and {$field} != 'http://'\n            ");
     }
     if ($ex->exists('phrase', array('product', 'fieldname')) === true) {
         # Dynamic vB user data (userfield)
         $profileFields = $ex->query("\n                select\n                    varname,\n                    text\n                from :_phrase\n                where product='vbulletin'\n                    and fieldname='cprofilefield'\n                    and varname like 'field%_title'\n            ");
         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[] = "\n                        insert into VbulletinUserMeta(UserID, Name, Value)\n                            select\n                                userid,\n                                'Profile." . $name . "',\n                                " . $column . "\n                            from :_userfield\n                            where " . $column . " != ''\n                    ";
             }
             foreach ($profileQueries as $query) {
                 $ex->query($query);
             }
         }
     }
     // Users meta informations
     $ex->exportTable('UserMeta', "\n            select\n                userid as UserID,\n                'Plugin.Signatures.Sig' as Name,\n                signature as Value\n            from :_usertextfield\n            where nullif(signature, '') is not null\n\n            union\n\n            select\n                userid,\n                'Plugin.Signatures.Format',\n                'BBCode'\n            from :_usertextfield\n            where nullif(signature, '') is not null\n\n            union\n\n            select\n                *\n            from VbulletinUserMeta\n        ");
     // 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\n                ut.*,\n                ut.title as title2,\n                0 as level\n            from :_usertitle as ut\n            order by ut.minposts\n        ", $rank_Map);
     // Categories
     $category_Map = array('title' => array('Column' => 'Name', 'Filter' => 'HTMLDecoder'), 'displayorder' => array('Column' => 'Sort', 'Type' => 'int'));
     $ex->exportTable('Category', "\n            select\n                f.forumid as CategoryID,\n                f.description as Description,\n                f.parentid as ParentCategoryID,\n                f.title,\n                f.displayorder\n            from :_forum as f\n            where 1 = 1\n                {$forumWhere}\n        ", $category_Map);
     $minDiscussionID = false;
     $minDiscussionWhere = false;
     if ($minDate) {
         $minDiscussionID = $ex->getValue("\n                select max(threadid)\n                from :_thread\n                where dateline < {$minDate}\n            ", false);
         $minDiscussionID2 = $ex->getValue("\n                select min(threadid)\n                from :_thread\n                where dateline >= {$minDate}\n            ", false);
         // The two discussion IDs should be the same, but let's average them.
         $minDiscussionID = floor(($minDiscussionID + $minDiscussionID2) / 2);
         $ex->comment('Min topic id: ' . $minDiscussionID);
     }
     // Discussions
     $discussion_Map = array('title' => array('Column' => 'Name', 'Filter' => 'HTMLDecoder'));
     if ($ex->destination == 'database') {
         // Remove the filter from the title so that this doesn't take too long.
         $ex->HTMLDecoderDb('thread', 'title', 'threadid');
         unset($discussion_Map['title']['Filter']);
     }
     if ($minDiscussionID) {
         $minDiscussionWhere = "and t.threadid > {$minDiscussionID}";
     }
     $ex->exportTable('Discussion', "\n            select\n                t.threadid as DiscussionID,\n                t.forumid as CategoryID,\n                t.postuserid as InsertUserID,\n                t.postuserid as UpdateUserID,\n                t.views as CountViews,\n                t.title,\n                p.postid as ForeignID,\n                p.ipaddress as InsertIPAddress,\n                p.pagetext as Body,\n                'BBCode' as Format,\n                replycount+1 as CountComments,\n                convert(ABS(open-1), char(1)) as Closed,\n                if(convert(sticky, char(1)) > 0, 2, 0) as Announce,\n                from_unixtime(t.dateline) as DateInserted,\n                from_unixtime(lastpost) as DateLastComment,\n                if (t.pollid > 0, 'Poll', null) as Type\n            from :_thread as t\n                left join :_deletionlog as d on d.type='thread' and d.primaryid=t.threadid\n                left join :_post as p on p.postid = t.firstpostid\n            where d.primaryid is null\n                and t.visible = 1\n            {$minDiscussionWhere}\n            {$forumWhere}\n        ", $discussion_Map);
     // Comments
     $comment_Map = array();
     if ($minDiscussionID) {
         $minDiscussionWhere = "and p.threadid > {$minDiscussionID}";
     }
     $ex->exportTable('Comment', "\n            select\n                p.postid as CommentID,\n                p.threadid as DiscussionID,\n                p.pagetext as Body,\n                p.ipaddress as InsertIPAddress,\n                'BBCode' as Format,\n                p.userid as InsertUserID,\n                p.userid as UpdateUserID,\n                from_unixtime(p.dateline) as DateInserted\n            from :_post as p\n                inner join :_thread as t on p.threadid = t.threadid\n                left join :_deletionlog as d on (d.type='post' and d.primaryid=p.postid)\n            where p.postid <> t.firstpostid\n                and d.primaryid is null\n                and p.visible = 1\n                {$minDiscussionWhere}\n                {$forumWhere}\n        ", $comment_Map);
     // UserDiscussion
     if ($minDiscussionID) {
         $minDiscussionWhere = "where st.threadid > {$minDiscussionID}";
     }
     if ($ex->exists('threadread', array('readtime')) === true) {
         $threadReadTime = 'from_unixtime(tr.readtime)';
         $threadReadJoin = 'left join :_threadread as tr on tr.userid = st.userid and tr.threadid = st.threadid';
     } else {
         $threadReadTime = 'now()';
         $threadReadJoin = null;
     }
     $ex->exportTable('UserDiscussion', "\n            select\n                st.userid as UserID,\n                st.threadid as DiscussionID,\n                {$threadReadTime} as DateLastViewed,\n                '1' as Bookmarked\n            from :_subscribethread as st\n                {$threadReadJoin}\n                {$minDiscussionWhere}\n        ");
     /*$ex->exportTable('UserDiscussion', "
           select
               tr.userid as UserID,
               tr.threadid as DiscussionID,
               from_unixtime(tr.readtime) as DateLastViewed,
               case
                   when st.threadid is not null then 1
                   else 0
               end as Bookmarked
           from :_threadread tr
           left join :_subscribethread st on tr.userid = st.userid and tr.threadid = st.threadid
       ");*/
     // Activity (from visitor messages in vBulletin 3.8+)
     if ($ex->exists('visitormessage') === true) {
         if ($minDiscussionID) {
             $minDiscussionWhere = "and dateline > {$minDiscussionID}";
         }
         $activity_Map = array('postuserid' => 'RegardingUserID', 'userid' => 'ActivityUserID', 'pagetext' => 'Story', 'NotifyUserID' => 'NotifyUserID', 'Format' => 'Format');
         $ex->exportTable('Activity', "\n                select\n                    vm.*,\n                    '{RegardingUserID,you} &rarr; {ActivityUserID,you}' as HeadlineFormat,\n                    from_unixtime(vm.dateline) as DateInserted,\n                    from_unixtime(vm.dateline) as DateUpdated,\n                    inet_ntoa(vm.ipaddress) as InsertIPAddress,\n                    vm.postuserid as InsertUserID,\n                    -1 as NotifyUserID,\n                    'BBCode' as Format,\n                    'WallPost' as ActivityType\n                from :_visitormessage as vm\n                where state='visible'\n                    {$minDiscussionWhere}\n            ", $activity_Map);
     }
     $this->_exportConversations($minDate);
     $this->_exportPolls();
     // Media
     if ($ex->exists('attachment') === true) {
         $this->exportMedia($minDiscussionID);
     }
     // IP Ban list
     $ipBanlist = $this->param('ipbanlist');
     if ($ipBanlist) {
         $ex->query("drop table if exists z_ipbanlist");
         $ex->query("\n                create table z_ipbanlist(\n                    id int(11) unsigned not null auto_increment,\n                    ipaddress varchar(50) default null,\n                    primary key (id),\n                    unique key ipaddress (ipaddress)\n                ) engine=InnoDB default charset=utf8\n            ");
         $result = $ex->query("select value from :_setting where varname = 'banip'");
         $row = mysql_fetch_assoc($result);
         if ($row) {
             $insertSql = 'insert ignore into z_ipbanlist(ipaddress) values ';
             $ipString = str_replace("\r", "", $row['value']);
             $IPs = explode("\n", $ipString);
             foreach ($IPs as $IP) {
                 $IP = trim($IP);
                 if (empty($IP)) {
                     continue;
                 }
                 $insertSql .= '(\'' . mysql_real_escape_string($IP) . '\'), ';
             }
             $insertSql = substr($insertSql, 0, -2);
             $ex->query($insertSql);
             $ban_Map = array();
             $ex->exportTable('Ban', "\n                    select\n                        'IPAddress' as BanType,\n                        ipaddress as BanValue,\n                        'Imported ban' as Notes,\n                        NOW() as DateInserted\n                    from z_ipbanlist\n                ", $ban_Map);
             $ex->query('drop table if exists z_ipbanlist');
         }
     }
     // End
     $ex->endExport();
 }
示例#2
0
 /**
  * Export each table one at a time.
  *
  * @param ExportModel $ex
  */
 protected function forumExport($ex)
 {
     // Allow limited export of 1 category via ?forumid=ID
     $forumID = $this->param('forumid');
     if ($forumID) {
         $forumWhere = ' and t.forumid ' . (strpos($forumID, ', ') === false ? "= {$forumID}" : "in ({$forumID})");
     } else {
         $forumWhere = '';
     }
     $characterSet = $ex->getCharacterSet('post');
     if ($characterSet) {
         $ex->characterSet = $characterSet;
     }
     // Begin
     $ex->beginExport('', 'vBulletin 3.* and 4.*');
     $this->exportBlobs($this->param('files'), $this->param('avatars'), $forumWhere);
     if ($this->param('noexport')) {
         $ex->comment('Skipping the export.');
         $ex->endExport();
         return;
     }
     // Check to see if there is a max date.
     $minDate = $this->param('mindate');
     if ($minDate) {
         $minDate = strtotime($minDate);
         $ex->comment("Min topic date ({$minDate}): " . date('c', $minDate));
     }
     $now = time();
     $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' => array('Column' => 'Title', 'Filter' => function ($value) {
         return trim(strip_tags(str_replace('&nbsp;', ' ', $value)));
     }), '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';
     }
     $ex->exportTable('User', "select u.*,\n            ipaddress as ipaddress2,\n            concat(`password`, salt) as password2,\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            'vbulletin' as HashMethod\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
     // 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) {
                     if (!$groupID) {
                         continue;
                     }
                     $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);
     //      $ex->EndExport();
     //      return;
     // 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)\n               select userid, 'Profile." . $name . "', " . $column . " from :_userfield where " . $column . " != ''";
         }
         foreach ($profileQueries as $query) {
             $ex->query($query);
         }
     }
     // Signatures
     $sql = "\n         select\n            userid as UserID,\n            'Plugin.Signatures.Sig' as Name,\n            signature as Value\n         from :_usertextfield\n         where nullif(signature, '') is not null\n\n         union\n\n         select\n            userid,\n            'Plugin.Signatures.Format',\n            'BBCode'\n         from :_usertextfield\n         where nullif(signature, '') is not null";
     $ex->exportTable('UserMeta', $sql);
     // 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);
     // Categories
     $category_Map = array('forumid' => 'CategoryID', 'description' => 'Description', 'Name2' => array('Column' => 'Name', 'Filter' => 'HTMLDecoder'), 'displayorder' => array('Column' => 'Sort', 'Type' => 'int'), 'parentid' => 'ParentCategoryID');
     $ex->exportTable('Category', "select f.*, title as Name2\n         from :_forum f\n         where 1 = 1 {$forumWhere}", $category_Map);
     $minDiscussionID = false;
     $minDiscussionWhere = false;
     if ($minDate) {
         $minDiscussionID = $ex->getValue("\n            select max(threadid)\n            from :_thread\n            where dateline < {$minDate}\n            ", false);
         $minDiscussionID2 = $ex->getValue("\n            select min(threadid)\n            from :_thread\n            where dateline >= {$minDate}\n            ", false);
         // The two discussion IDs should be the same, but let's average them.
         $minDiscussionID = floor(($minDiscussionID + $minDiscussionID2) / 2);
         $ex->comment('Min topic id: ' . $minDiscussionID);
     }
     // Discussions
     $discussion_Map = array('threadid' => 'DiscussionID', 'forumid' => 'CategoryID', 'postuserid' => 'InsertUserID', 'postuserid2' => 'UpdateUserID', 'title' => array('Column' => 'Name', 'Filter' => 'HTMLDecoder'), 'Format' => 'Format', 'views' => 'CountViews', 'ipaddress' => 'InsertIPAddress');
     if ($ex->destination == 'database') {
         // Remove the filter from the title so that this doesn't take too long.
         $ex->HTMLDecoderDb('thread', 'title', 'threadid');
         unset($discussion_Map['title']['Filter']);
     }
     if ($minDiscussionID) {
         $minDiscussionWhere = "and t.threadid > {$minDiscussionID}";
     }
     $ex->exportTable('Discussion', "select t.*,\n            t.postuserid as postuserid2,\n            p.ipaddress,\n            p.pagetext as Body,\n            'BBCode' as Format,\n            replycount+1 as CountComments,\n            convert(ABS(open-1),char(1)) as Closed,\n            if(convert(sticky,char(1))>0,2,0) as Announce,\n            FROM_UNIXTIME(t.dateline) as DateInserted,\n            FROM_UNIXTIME(lastpost) as DateUpdated,\n            FROM_UNIXTIME(lastpost) as DateLastComment\n         from :_thread t\n            left join :_deletionlog d on (d.type='thread' and d.primaryid=t.threadid)\n            left join :_post p on p.postid = t.firstpostid\n         where d.primaryid is null\n            and t.visible = 1\n            {$minDiscussionWhere}\n            {$forumWhere}", $discussion_Map);
     // Comments
     $comment_Map = array('postid' => 'CommentID', 'threadid' => 'DiscussionID', 'pagetext' => 'Body', 'Format' => 'Format', 'ipaddress' => 'InsertIPAddress');
     if ($minDiscussionID) {
         $minDiscussionWhere = "and p.threadid > {$minDiscussionID}";
     }
     $ex->exportTable('Comment', "select p.*,\n            'BBCode' as Format,\n            p.userid as InsertUserID,\n            p.userid as UpdateUserID,\n         FROM_UNIXTIME(p.dateline) as DateInserted,\n            FROM_UNIXTIME(p.dateline) as DateUpdated\n         from :_post p\n         inner join :_thread t\n            on p.threadid = t.threadid\n         left join :_deletionlog d\n            on (d.type='post' and d.primaryid=p.postid)\n         where p.postid <> t.firstpostid\n            and d.primaryid is null\n            and p.visible = 1\n            {$minDiscussionWhere}\n            {$forumWhere}", $comment_Map);
     // UserDiscussion
     if ($minDiscussionID) {
         $minDiscussionWhere = "where st.threadid > {$minDiscussionID}";
     }
     $ex->exportTable('UserDiscussion', "select\n            st.userid as UserID,\n            st.threadid as DiscussionID,\n            '1' as Bookmarked,\n            FROM_UNIXTIME(tr.readtime) as DateLastViewed\n         from :_subscribethread st\n         left join :_threadread tr on tr.userid = st.userid and tr.threadid = st.threadid\n         {$minDiscussionWhere}");
     /*$ex->exportTable('UserDiscussion', "select
         tr.userid as UserID,
         tr.threadid as DiscussionID,
         FROM_UNIXTIME(tr.readtime) as DateLastViewed,
         case when st.threadid is not null then 1 else 0 end as Bookmarked
       from :_threadread tr
       left join :_subscribethread st on tr.userid = st.userid and tr.threadid = st.threadid");*/
     // Activity (from visitor messages in vBulletin 3.8+)
     if ($ex->exists('visitormessage')) {
         if ($minDiscussionID) {
             $minDiscussionWhere = "and dateline > {$minDiscussionID}";
         }
         $activity_Map = array('postuserid' => 'RegardingUserID', 'userid' => 'ActivityUserID', 'pagetext' => 'Story', 'NotifyUserID' => 'NotifyUserID', 'Format' => 'Format');
         $ex->exportTable('Activity', "select *,\n               '{RegardingUserID,you} &rarr; {ActivityUserID,you}' as HeadlineFormat,\n               FROM_UNIXTIME(dateline) as DateInserted,\n               FROM_UNIXTIME(dateline) as DateUpdated,\n               INET_NTOA(ipaddress) as InsertIPAddress,\n               postuserid as InsertUserID,\n               -1 as NotifyUserID,\n               'BBCode' as Format,\n               'WallPost' as ActivityType\n            from :_visitormessage\n            where state='visible'\n               {$minDiscussionWhere}", $activity_Map);
     }
     $this->_exportConversations($minDate);
     $this->_exportPolls();
     // Media
     if ($ex->exists('attachment')) {
         $this->exportMedia($minDiscussionID);
     }
     // IP Ban list
     $ipBanlist = $this->param('ipbanlist');
     if ($ipBanlist) {
         $ex->query("DROP TABLE IF EXISTS `z_ipbanlist` ");
         $ex->query("CREATE TABLE `z_ipbanlist` (\n            `id` int(11) unsigned NOT NULL AUTO_INCREMENT,\n            `ipaddress` varchar(50) DEFAULT NULL,\n           PRIMARY KEY (`id`),\n           UNIQUE KEY `ipaddress` (`ipaddress`)\n\n         ) ENGINE=InnoDB DEFAULT CHARSET=utf8");
         $result = $ex->query("select value from :_setting where varname = 'banip'");
         $row = mysql_fetch_assoc($result);
         if ($row) {
             $insertSql = 'INSERT IGNORE INTO `z_ipbanlist` (`ipaddress`) values ';
             $ipString = str_replace("\r", "", $row['value']);
             $IPs = explode("\n", $ipString);
             foreach ($IPs as $IP) {
                 $IP = trim($IP);
                 if (empty($IP)) {
                     continue;
                 }
                 $insertSql .= '(\'' . mysql_real_escape_string($IP) . '\'), ';
             }
             $insertSql = substr($insertSql, 0, -2);
             $ex->query($insertSql);
             $ban_Map = array();
             $ex->exportTable('Ban', "select 'IPAddress' as BanType, ipaddress as BanValue, 'Imported ban' as Notes, NOW() as DateInserted\n                  FROM `z_ipbanlist`", $ban_Map);
             $ex->query('DROP table if exists `z_ipbanlist` ');
         }
     }
     // End
     $ex->endExport();
 }
示例#3
0
 /**
  *
  * @param ExportModel $ex
  */
 public function forumExport($ex)
 {
     $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, case when scheme = 'legacy' then 'vbulletin' else 'vbulletin5' end as HashMethod,";
     }
     $ex->exportTable('User', "\n            select\n                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 on u.userid = a.userid\n                left join :_avatar av on u.avatarid = av.avatarid\n                left join :_userban ub\n                    on u.userid = ub.userid\n                    and ub.liftdate <= now()\n         ;", $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\n                ut.*,\n                ut.title as title2,\n                0 as level\n            from :_usertitle ut\n            order by ut.minposts\n         ;", $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("\n            select\n                n.*\n            from :_node n\n                left join :_contenttype ct on n.contenttypeid = ct.contenttypeid\n            where ct.class = 'Channel'\n        ;");
     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', "\n            select\n                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', 'type' => 'Type', 'title' => 'Name', 'userid' => 'InsertUserID', 'rawtext' => 'Body', 'parentid' => 'CategoryID', 'lastcontentid' => 'LastCommentID', 'lastauthorid' => 'LastCommentUserID');
     $discussionQuery = "\n            select\n                n.nodeid,\n                null as type,\n                n.title,\n                n.userid,\n                t.rawtext,\n                n.parentid,\n                n.lastcontentid,\n                n.lastauthorid,\n                'BBCode' as Format,\n                FROM_UNIXTIME(publishdate) as DateInserted,\n                v.count as CountViews,\n                convert(ABS(n.open-1),char(1)) as Closed,\n                if(convert(n.sticky,char(1))>0,2,0) as Announce,\n                null as PollID\n            from :_node n\n                left join :_contenttype ct on n.contenttypeid = ct.contenttypeid\n                left join :_nodeview v on v.nodeid = n.nodeid\n                left join :_text t on t.nodeid = n.nodeid\n            where ct.class = 'Text'\n                and n.showpublished = 1\n                and parentid in (" . implode(',', $categoryIDs) . ")\n        ;";
     // Polls need to be wrapped in a discussion so we are gonna need to postpone discussion creations
     if ($this->_getPollsCount()) {
         // NOTE: Only polls that are directly under a channel (discussion) will be exported.
         // Vanilla poll plugin does not support polls as comments.
         $ex->query("drop table if exists vBulletinDiscussionTable;");
         // Create a temporary table to hold old discussions and to create new discussions for polls
         $ex->query("\n                create table `vBulletinDiscussionTable` (\n                    `nodeid` int(10) unsigned not null AUTO_INCREMENT,\n                    `type` varchar(10) default null,\n                    `title` varchar(255) default null,\n                    `userid` int(10) unsigned default null,\n                    `rawtext` mediumtext,\n                    `parentid` int(11) not null,\n                    `lastcontentid` int(11) not null default '0',\n                    `lastauthorid` int(10) unsigned not null default '0',\n                    `Format` varchar(10) not null,\n                    `DateInserted` datetime not null,\n                    `CountViews` int(11) not null default '1',\n                    `Closed` tinyint(4) not null default '0',\n                    `Announce` tinyint(4) not null default '0',\n                    `PollID` int(10) unsigned, /* used to create poll->discussion mapping */\n                    primary key (`nodeid`)\n                )\n            ;");
         $ex->query("insert into vBulletinDiscussionTable {$discussionQuery}");
         $this->_generatePollsDiscussion();
         // Export discussions
         $sql = "\n                select\n                    nodeid,\n                    type,\n                    title,\n                    userid,\n                    rawtext,\n                    parentid,\n                    lastcontentid,\n                    lastauthorid,\n                    Format,\n                    DateInserted,\n                    CountViews,\n                    Closed,\n                    Announce\n                from vBulletinDiscussionTable\n            ;";
         $ex->exportTable('Discussion', $sql, $discussion_Map);
         // Export polls
         $this->_exportPolls();
         // Cleanup tmp table
         $ex->query("drop table vBulletinDiscussionTable;");
     } else {
         $ex->exportTable('Discussion', $discussionQuery, $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', "\n            select\n                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', "\n            select\n                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
     $instance = $this;
     // 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' => function ($value, $field, $row) use($instance) {
         $filteredData = $this->filterThumbnailData($value, $field, $row);
         if ($filteredData) {
             return $instance->buildMediaPath($value, $field, $row);
         } else {
             return null;
         }
     }), 'thumb_width' => array('Column' => 'ThumbWidth', 'Filter' => array($this, 'filterThumbnailData')), 'width' => 'ImageWidth', 'height' => 'ImageHeight', 'filesize' => 'Size');
     $ex->exportTable('Media', "\n            select\n                a.*,\n                filename as Path2,\n                filename as ThumbPath2,\n                128 as thumb_width,\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                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', "\n            select\n                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 <> ''\n        ;", $conversation_Map);
     // Conversation Messages.
     $conversationMessage_Map = array('nodeid' => 'MessageID', 'rawtext' => 'Body', 'userid' => 'InsertUserID');
     $ex->exportTable('ConversationMessage', "\n            select\n                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 <> ''\n        ;", $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', "\n            select\n                s.*\n            from :_sentto s\n        ;", $userConversation_Map);
     /// Groups
     // class='SocialGroup'
     // class='SocialGroupDiscussion'
     // class='SocialGroupMessage'
     $ex->endExport();
 }