- Timestamp:
- 03/02/18 15:55:06 (7 years ago)
- Branch:
- default
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
plugins/importExport/inc/class.dc.import.dc1.php
r3606 r3725 10 10 # 11 11 # -- END LICENSE BLOCK ----------------------------------------- 12 if (!defined('DC_RC_PATH')) { return;}12 if (!defined('DC_RC_PATH')) {return;} 13 13 14 14 class dcImportDC1 extends dcIeModule 15 15 { 16 protected $con; 17 protected $prefix; 18 protected $blog_id; 19 20 protected $action = null; 21 protected $step = 1; 22 23 protected $post_offset = 0; 24 protected $post_limit = 20; 25 protected $post_count = 0; 26 27 protected $has_table = array(); 28 29 protected $vars; 30 protected $base_vars = array( 31 'db_driver' => 'mysql', 32 'db_host' => '', 33 'db_name' => '', 34 'db_user' => '', 35 'db_pwd' => '', 36 'db_prefix' => 'dc_', 37 'post_limit' => 20, 38 'cat_ids' => array() 39 ); 40 41 protected function setInfo() 42 { 43 $this->type = 'import'; 44 $this->name = __('Dotclear 1.2 import'); 45 $this->description = __('Import a Dotclear 1.2 installation into your current blog.'); 46 } 47 48 public function init() 49 { 50 $this->con =& $this->core->con; 51 $this->prefix = $this->core->prefix; 52 $this->blog_id = $this->core->blog->id; 53 54 if (!isset($_SESSION['dc1_import_vars'])) { 55 $_SESSION['dc1_import_vars'] = $this->base_vars; 56 } 57 $this->vars =& $_SESSION['dc1_import_vars']; 58 59 if ($this->vars['post_limit'] > 0) { 60 $this->post_limit = $this->vars['post_limit']; 61 } 62 } 63 64 public function resetVars() 65 { 66 $this->vars = $this->base_vars;; 67 unset($_SESSION['dc1_import_vars']); 68 } 69 70 public function process($do) 71 { 72 $this->action = $do; 73 } 74 75 # We handle process in another way to always display something to 76 # user 77 protected function guiprocess($do) 78 { 79 switch ($do) 80 { 81 case 'step1': 82 $this->vars['db_driver'] = $_POST['db_driver']; 83 $this->vars['db_host'] = $_POST['db_host']; 84 $this->vars['db_name'] = $_POST['db_name']; 85 $this->vars['db_user'] = $_POST['db_user']; 86 $this->vars['db_pwd'] = $_POST['db_pwd']; 87 $this->vars['post_limit'] = abs((integer) $_POST['post_limit']) > 0 ? $_POST['post_limit'] : 0; 88 $this->vars['db_prefix'] = $_POST['db_prefix']; 89 $db = $this->db(); 90 $db->close(); 91 $this->step = 2; 92 echo $this->progressBar(1); 93 break; 94 case 'step2': 95 $this->step = 2; 96 $this->importUsers(); 97 $this->step = 3; 98 echo $this->progressBar(3); 99 break; 100 case 'step3': 101 $this->step = 3; 102 $this->importCategories(); 103 if ($this->core->plugins->moduleExists('blogroll')) { 104 $this->step = 4; 105 echo $this->progressBar(5); 106 } else { 107 $this->step = 5; 108 echo $this->progressBar(7); 109 } 110 break; 111 case 'step4': 112 $this->step = 4; 113 $this->importLinks(); 114 $this->step = 5; 115 echo $this->progressBar(7); 116 break; 117 case 'step5': 118 $this->step = 5; 119 $this->post_offset = !empty($_REQUEST['offset']) ? abs((integer) $_REQUEST['offset']) : 0; 120 if ($this->importPosts($percent) === -1) { 121 http::redirect($this->getURL().'&do=ok'); 122 } else { 123 echo $this->progressBar(ceil($percent*0.93)+7); 124 } 125 break; 126 case 'ok': 127 $this->resetVars(); 128 $this->core->blog->triggerBlog(); 129 $this->step = 6; 130 echo $this->progressBar(100); 131 break; 132 } 133 } 134 135 public function gui() 136 { 137 try { 138 $this->guiprocess($this->action); 139 } catch (Exception $e) { 140 $this->error($e); 141 } 142 143 # db drivers 144 $db_drivers = array( 145 'mysql' => 'mysql', 146 'mysqli' => 'mysqli' 147 ); 148 149 switch ($this->step) 150 { 151 case 1: 152 echo 153 '<p>'.sprintf(__('Import the content of a Dotclear 1.2\'s blog in the current blog: %s.'), 154 '<strong>'.html::escapeHTML($this->core->blog->name).'</strong>').'</p>'. 155 '<p class="warning">'.__('Please note that this process '. 156 'will empty your categories, blogroll, entries and comments on the current blog.').'</p>'; 157 158 printf($this->imForm(1,__('General information'),__('Import my blog now')), 159 '<p>'.__('We first need some information about your old Dotclear 1.2 installation.').'</p>'. 160 '<p><label for="db_driver">'.__('Database driver (must be mysqli if PHP 7 or higher):').'</label> '. 161 form::combo('db_driver',$db_drivers,html::escapeHTML($this->vars['db_driver'])).'</p>'. 162 '<p><label for="db_host">'.__('Database Host Name:').'</label> '. 163 form::field('db_host',30,255,html::escapeHTML($this->vars['db_host'])).'</p>'. 164 '<p><label for="db_name">'.__('Database Name:',html::escapeHTML($this->vars['db_name'])).'</label> '. 165 form::field('db_name',30,255,html::escapeHTML($this->vars['db_name'])).'</p>'. 166 '<p><label for="db_user">'.__('Database User Name:').'</label> '. 167 form::field('db_user',30,255,html::escapeHTML($this->vars['db_user'])).'</p>'. 168 '<p><label for="db_pwd">'.__('Database Password:').'</label> '. 169 form::password('db_pwd',30,255).'</p>'. 170 '<p><label for="db_prefix">'.__('Database Tables Prefix:').'</label> '. 171 form::field('db_prefix',30,255,html::escapeHTML($this->vars['db_prefix'])).'</p>'. 172 '<h3 class="vertical-separator">'.__('Entries import options').'</h3>'. 173 '<p><label for="post_limit">'.__('Number of entries to import at once:').'</label> '. 174 form::field('post_limit',3,3,html::escapeHTML($this->vars['post_limit'])).'</p>' 175 ); 176 break; 177 case 2: 178 printf($this->imForm(2,__('Importing users')), 179 $this->autoSubmit() 180 ); 181 break; 182 case 3: 183 printf($this->imForm(3,__('Importing categories')), 184 $this->autoSubmit() 185 ); 186 break; 187 case 4: 188 printf($this->imForm(4,__('Importing blogroll')), 189 $this->autoSubmit() 190 ); 191 break; 192 case 5: 193 $t = sprintf(__('Importing entries from %d to %d / %d'),$this->post_offset, 194 min(array($this->post_offset+$this->post_limit,$this->post_count)),$this->post_count); 195 printf($this->imForm(5,$t), 196 form::hidden(array('offset'),$this->post_offset). 197 $this->autoSubmit() 198 ); 199 break; 200 case 6: 201 echo 202 '<h3 class="vertical-separator">'.__('Please read carefully').'</h3>'. 203 '<ul>'. 204 '<li>'.__('Every newly imported user has received a random password '. 205 'and will need to ask for a new one by following the "I forgot my password" link on the login page '. 206 '(Their registered email address has to be valid.)').'</li>'. 207 208 '<li>'.sprintf(__('Please note that Dotclear 2 has a new URL layout. You can avoid broken '. 209 'links by installing <a href="%s">DC1 redirect</a> plugin and activate it in your blog configuration.'), 210 'http://plugins.dotaddict.org/dc2/details/dc1redirect').'</li>'. 211 '</ul>'. 212 213 $this->congratMessage(); 214 215 break; 216 } 217 } 218 219 # Simple form for step by step process 220 protected function imForm($step,$legend,$submit_value=null) 221 { 222 if (!$submit_value) { 223 $submit_value = __('next step').' >'; 224 } 225 226 return 227 '<form action="'.$this->getURL(true).'" method="post">'. 228 '<h3 class="vertical-separator">'.$legend.'</h3>'. 229 '<div>'.$this->core->formNonce(). 230 form::hidden(array('do'),'step'.$step). 231 '%s'.'</div>'. 232 '<p class="vertical-separator"><input type="submit" value="'.$submit_value.'" /></p>'. 233 '<p class="form-note info">'.__('Depending on the size of your blog, it could take a few minutes.').'</p>'. 234 '</form>'; 235 } 236 237 # Error display 238 protected function error($e) 239 { 240 echo '<div class="error"><strong>'.__('Errors:').'</strong>'. 241 '<p>'.$e->getMessage().'</p></div>'; 242 } 243 244 # Database init 245 protected function db() 246 { 247 $db = dbLayer::init($this->vars['db_driver'],$this->vars['db_host'],$this->vars['db_name'],$this->vars['db_user'],$this->vars['db_pwd']); 248 249 $rs = $db->select("SHOW TABLES LIKE '".$this->vars['db_prefix']."%'"); 250 if ($rs->isEmpty()) { 251 throw new Exception(__('Dotclear tables not found')); 252 } 253 254 while ($rs->fetch()) { 255 $this->has_table[$rs->f(0)] = true; 256 } 257 258 # Set this to read data as they were written in Dotclear 1 259 try { 260 $db->execute('SET NAMES DEFAULT'); 261 } catch (Exception $e) {} 262 263 $db->execute('SET CHARACTER SET DEFAULT'); 264 $db->execute("SET COLLATION_CONNECTION = DEFAULT"); 265 $db->execute("SET COLLATION_SERVER = DEFAULT"); 266 $db->execute("SET CHARACTER_SET_SERVER = DEFAULT"); 267 $db->execute("SET CHARACTER_SET_DATABASE = DEFAULT"); 268 269 $this->post_count = $db->select( 270 'SELECT COUNT(post_id) FROM '.$this->vars['db_prefix'].'post ' 271 )->f(0); 272 273 return $db; 274 } 275 276 protected function cleanStr($str) 277 { 278 return text::cleanUTF8(@text::toUTF8($str)); 279 } 280 281 # Users import 282 protected function importUsers() 283 { 284 $db = $this->db(); 285 $prefix = $this->vars['db_prefix']; 286 $rs = $db->select('SELECT * FROM '.$prefix.'user'); 287 288 try 289 { 290 $this->con->begin(); 291 292 while ($rs->fetch()) 293 { 294 if (!$this->core->userExists($rs->user_id)) 295 { 296 $cur = $this->con->openCursor($this->prefix.'user'); 297 $cur->user_id = $rs->user_id; 298 $cur->user_name = $rs->user_nom; 299 $cur->user_firstname = $rs->user_prenom; 300 $cur->user_displayname = $rs->user_pseudo; 301 $cur->user_pwd = crypt::createPassword(); 302 $cur->user_email = $rs->user_email; 303 $cur->user_lang = $rs->user_lang; 304 $cur->user_tz = $this->core->blog->settings->system->blog_timezone; 305 $cur->user_post_status = $rs->user_post_pub ? 1 : -2; 306 $cur->user_options = new ArrayObject(array( 307 'edit_size' => (integer) $rs->user_edit_size, 308 'post_format' => $rs->user_post_format 309 )); 310 311 $permissions = array(); 312 switch ($rs->user_level) 313 { 314 case '0': 315 $cur->user_status = 0; 316 break; 317 case '1': # editor 318 $permissions['usage'] = true; 319 break; 320 case '5': # advanced editor 321 $permissions['contentadmin'] = true; 322 $permissions['categories'] = true; 323 $permissions['media_admin'] = true; 324 break; 325 case '9': # admin 326 $permissions['admin'] = true; 327 break; 328 } 329 330 $this->core->addUser($cur); 331 $this->core->setUserBlogPermissions( 332 $rs->user_id, 333 $this->blog_id, 334 $permissions 335 ); 336 } 337 } 338 339 $this->con->commit(); 340 $db->close(); 341 } 342 catch (Exception $e) 343 { 344 $this->con->rollback(); 345 $db->close(); 346 throw $e; 347 } 348 } 349 350 # Categories import 351 protected function importCategories() 352 { 353 $db = $this->db(); 354 $prefix = $this->vars['db_prefix']; 355 $rs = $db->select('SELECT * FROM '.$prefix.'categorie ORDER BY cat_ord ASC'); 356 357 try 358 { 359 $this->con->execute( 360 'DELETE FROM '.$this->prefix.'category '. 361 "WHERE blog_id = '".$this->con->escape($this->blog_id)."' " 362 ); 363 364 $ord = 2; 365 while ($rs->fetch()) 366 { 367 $cur = $this->con->openCursor($this->prefix.'category'); 368 $cur->blog_id = $this->blog_id; 369 $cur->cat_title = $this->cleanStr(htmlspecialchars_decode($rs->cat_libelle)); 370 $cur->cat_desc = $this->cleanStr($rs->cat_desc); 371 $cur->cat_url = $this->cleanStr($rs->cat_libelle_url); 372 $cur->cat_lft = $ord++; 373 $cur->cat_rgt = $ord++; 374 375 $cur->cat_id = $this->con->select( 376 'SELECT MAX(cat_id) FROM '.$this->prefix.'category' 377 )->f(0) + 1; 378 $this->vars['cat_ids'][$rs->cat_id] = $cur->cat_id; 379 $cur->insert(); 380 } 381 382 $db->close(); 383 } 384 catch (Exception $e) 385 { 386 $db->close(); 387 throw $e; 388 } 389 } 390 391 # Blogroll import 392 protected function importLinks() 393 { 394 $db = $this->db(); 395 $prefix = $this->vars['db_prefix']; 396 $rs = $db->select('SELECT * FROM '.$prefix.'link ORDER BY link_id ASC'); 397 398 try 399 { 400 $this->con->execute( 401 'DELETE FROM '.$this->prefix.'link '. 402 "WHERE blog_id = '".$this->con->escape($this->blog_id)."' " 403 ); 404 405 while ($rs->fetch()) 406 { 407 $cur = $this->con->openCursor($this->prefix.'link'); 408 $cur->blog_id = $this->blog_id; 409 $cur->link_href = $this->cleanStr($rs->href); 410 $cur->link_title = $this->cleanStr($rs->label); 411 $cur->link_desc = $this->cleanStr($rs->title); 412 $cur->link_lang = $this->cleanStr($rs->lang); 413 $cur->link_xfn = $this->cleanStr($rs->rel); 414 $cur->link_position = (integer) $rs->position; 415 416 $cur->link_id = $this->con->select( 417 'SELECT MAX(link_id) FROM '.$this->prefix.'link' 418 )->f(0) + 1; 419 $cur->insert(); 420 } 421 422 $db->close(); 423 } 424 catch (Exception $e) 425 { 426 $db->close(); 427 throw $e; 428 } 429 } 430 431 # Entries import 432 protected function importPosts(&$percent) 433 { 434 $db = $this->db(); 435 $prefix = $this->vars['db_prefix']; 436 437 $count = $db->select('SELECT COUNT(post_id) FROM '.$prefix.'post')->f(0); 438 439 $rs = $db->select( 440 'SELECT * FROM '.$prefix.'post ORDER BY post_id ASC '. 441 $db->limit($this->post_offset,$this->post_limit) 442 ); 443 444 try 445 { 446 if ($this->post_offset == 0) 447 { 448 $this->con->execute( 449 'DELETE FROM '.$this->prefix.'post '. 450 "WHERE blog_id = '".$this->con->escape($this->blog_id)."' " 451 ); 452 } 453 454 while ($rs->fetch()) { 455 $this->importPost($rs,$db); 456 } 457 458 $db->close(); 459 } 460 catch (Exception $e) 461 { 462 $db->close(); 463 throw $e; 464 } 465 466 if ($rs->count() < $this->post_limit) { 467 return -1; 468 } else { 469 $this->post_offset += $this->post_limit; 470 } 471 472 if ($this->post_offset > $this->post_count) { 473 $percent = 100; 474 } else { 475 $percent = $this->post_offset * 100 / $this->post_count; 476 } 477 } 478 479 protected function importPost($rs,$db) 480 { 481 $cur = $this->con->openCursor($this->prefix.'post'); 482 $cur->blog_id = $this->blog_id; 483 $cur->user_id = $rs->user_id; 484 $cur->cat_id = (integer) $this->vars['cat_ids'][$rs->cat_id]; 485 $cur->post_dt = $rs->post_dt; 486 $cur->post_creadt = $rs->post_creadt; 487 $cur->post_upddt = $rs->post_upddt; 488 $cur->post_title = html::decodeEntities($this->cleanStr($rs->post_titre)); 489 490 $cur->post_url = date('Y/m/d/',strtotime($cur->post_dt)).$rs->post_id.'-'.$rs->post_titre_url; 491 $cur->post_url = substr($cur->post_url,0,255); 492 493 $cur->post_format = $rs->post_content_wiki == '' ? 'xhtml' : 'wiki'; 494 $cur->post_content_xhtml = $this->cleanStr($rs->post_content); 495 $cur->post_excerpt_xhtml = $this->cleanStr($rs->post_chapo); 496 497 if ($cur->post_format == 'wiki') { 498 $cur->post_content = $this->cleanStr($rs->post_content_wiki); 499 $cur->post_excerpt = $this->cleanStr($rs->post_chapo_wiki); 500 } else { 501 $cur->post_content = $this->cleanStr($rs->post_content); 502 $cur->post_excerpt = $this->cleanStr($rs->post_chapo); 503 } 504 505 $cur->post_notes = $this->cleanStr($rs->post_notes); 506 $cur->post_status = (integer) $rs->post_pub; 507 $cur->post_selected = (integer) $rs->post_selected; 508 $cur->post_open_comment = (integer) $rs->post_open_comment; 509 $cur->post_open_tb = (integer) $rs->post_open_tb; 510 $cur->post_lang = $rs->post_lang; 511 512 $cur->post_words = implode(' ',text::splitWords( 513 $cur->post_title.' '. 514 $cur->post_excerpt_xhtml.' '. 515 $cur->post_content_xhtml 516 )); 517 518 $cur->post_id = $this->con->select( 519 'SELECT MAX(post_id) FROM '.$this->prefix.'post' 520 )->f(0) + 1; 521 522 $cur->insert(); 523 $this->importComments($rs->post_id,$cur->post_id,$db); 524 $this->importPings($rs->post_id,$cur->post_id,$db); 525 526 # Load meta if we have some in DC1 527 if (isset($this->has_table[$this->vars['db_prefix'].'post_meta'])) { 528 $this->importMeta($rs->post_id,$cur->post_id,$db); 529 } 530 } 531 532 # Comments import 533 protected function importComments($post_id,$new_post_id,$db) 534 { 535 $count_c = $count_t = 0; 536 537 $rs = $db->select( 538 'SELECT * FROM '.$this->vars['db_prefix'].'comment '. 539 'WHERE post_id = '.(integer) $post_id.' ' 540 ); 541 542 while ($rs->fetch()) 543 { 544 $cur = $this->con->openCursor($this->prefix.'comment'); 545 $cur->post_id = (integer) $new_post_id; 546 $cur->comment_author = $this->cleanStr($rs->comment_auteur); 547 $cur->comment_status = (integer) $rs->comment_pub; 548 $cur->comment_dt = $rs->comment_dt; 549 $cur->comment_upddt = $rs->comment_upddt; 550 $cur->comment_email = $this->cleanStr($rs->comment_email); 551 $cur->comment_content = $this->cleanStr($rs->comment_content); 552 $cur->comment_ip = $rs->comment_ip; 553 $cur->comment_trackback = (integer) $rs->comment_trackback; 554 555 $cur->comment_site = $this->cleanStr($rs->comment_site); 556 if ($cur->comment_site != '' && !preg_match('!^http://.*$!',$cur->comment_site)) { 557 $cur->comment_site = substr('http://'.$cur->comment_site,0,255); 558 } 559 560 if ($rs->exists('spam') && $rs->spam && $rs->comment_status = 0) { 561 $cur->comment_status = -2; 562 } 563 564 $cur->comment_words = implode(' ',text::splitWords($cur->comment_content)); 565 566 $cur->comment_id = $this->con->select( 567 'SELECT MAX(comment_id) FROM '.$this->prefix.'comment' 568 )->f(0) + 1; 569 570 $cur->insert(); 571 572 if ($cur->comment_trackback && $cur->comment_status == 1) { 573 $count_t++; 574 } elseif ($cur->comment_status == 1) { 575 $count_c++; 576 } 577 } 578 579 if ($count_t > 0 || $count_c > 0) 580 { 581 $this->con->execute( 582 'UPDATE '.$this->prefix.'post SET '. 583 'nb_comment = '.$count_c.', '. 584 'nb_trackback = '.$count_t.' '. 585 'WHERE post_id = '.(integer) $new_post_id.' ' 586 ); 587 } 588 } 589 590 # Pings import 591 protected function importPings($post_id,$new_post_id,$db) 592 { 593 $urls = array(); 594 595 $rs = $db->select( 596 'SELECT * FROM '.$this->vars['db_prefix'].'ping '. 597 'WHERE post_id = '.(integer) $post_id 598 ); 599 600 while ($rs->fetch()) 601 { 602 $url = $this->cleanStr($rs->ping_url); 603 if (isset($urls[$url])) { 604 continue; 605 } 606 607 $cur = $this->con->openCursor($this->prefix.'ping'); 608 $cur->post_id = (integer) $new_post_id; 609 $cur->ping_url = $url; 610 $cur->ping_dt = $rs->ping_dt; 611 $cur->insert(); 612 613 $urls[$url] = true; 614 } 615 } 616 617 # Meta import 618 protected function importMeta($post_id,$new_post_id,$db) 619 { 620 $rs = $db->select( 621 'SELECT * FROM '.$this->vars['db_prefix'].'post_meta '. 622 'WHERE post_id = '.(integer) $post_id.' ' 623 ); 624 625 if ($rs->isEmpty()) { 626 return; 627 } 628 629 while ($rs->fetch()) { 630 $this->core->meta->setPostMeta($new_post_id,$this->cleanStr($rs->meta_key),$this->cleanStr($rs->meta_value)); 631 } 632 } 16 protected $con; 17 protected $prefix; 18 protected $blog_id; 19 20 protected $action = null; 21 protected $step = 1; 22 23 protected $post_offset = 0; 24 protected $post_limit = 20; 25 protected $post_count = 0; 26 27 protected $has_table = array(); 28 29 protected $vars; 30 protected $base_vars = array( 31 'db_driver' => 'mysql', 32 'db_host' => '', 33 'db_name' => '', 34 'db_user' => '', 35 'db_pwd' => '', 36 'db_prefix' => 'dc_', 37 'post_limit' => 20, 38 'cat_ids' => array() 39 ); 40 41 protected function setInfo() 42 { 43 $this->type = 'import'; 44 $this->name = __('Dotclear 1.2 import'); 45 $this->description = __('Import a Dotclear 1.2 installation into your current blog.'); 46 } 47 48 public function init() 49 { 50 $this->con = &$this->core->con; 51 $this->prefix = $this->core->prefix; 52 $this->blog_id = $this->core->blog->id; 53 54 if (!isset($_SESSION['dc1_import_vars'])) { 55 $_SESSION['dc1_import_vars'] = $this->base_vars; 56 } 57 $this->vars = &$_SESSION['dc1_import_vars']; 58 59 if ($this->vars['post_limit'] > 0) { 60 $this->post_limit = $this->vars['post_limit']; 61 } 62 } 63 64 public function resetVars() 65 { 66 $this->vars = $this->base_vars; 67 unset($_SESSION['dc1_import_vars']); 68 } 69 70 public function process($do) 71 { 72 $this->action = $do; 73 } 74 75 # We handle process in another way to always display something to 76 # user 77 protected function guiprocess($do) 78 { 79 switch ($do) { 80 case 'step1': 81 $this->vars['db_driver'] = $_POST['db_driver']; 82 $this->vars['db_host'] = $_POST['db_host']; 83 $this->vars['db_name'] = $_POST['db_name']; 84 $this->vars['db_user'] = $_POST['db_user']; 85 $this->vars['db_pwd'] = $_POST['db_pwd']; 86 $this->vars['post_limit'] = abs((integer) $_POST['post_limit']) > 0 ? $_POST['post_limit'] : 0; 87 $this->vars['db_prefix'] = $_POST['db_prefix']; 88 $db = $this->db(); 89 $db->close(); 90 $this->step = 2; 91 echo $this->progressBar(1); 92 break; 93 case 'step2': 94 $this->step = 2; 95 $this->importUsers(); 96 $this->step = 3; 97 echo $this->progressBar(3); 98 break; 99 case 'step3': 100 $this->step = 3; 101 $this->importCategories(); 102 if ($this->core->plugins->moduleExists('blogroll')) { 103 $this->step = 4; 104 echo $this->progressBar(5); 105 } else { 106 $this->step = 5; 107 echo $this->progressBar(7); 108 } 109 break; 110 case 'step4': 111 $this->step = 4; 112 $this->importLinks(); 113 $this->step = 5; 114 echo $this->progressBar(7); 115 break; 116 case 'step5': 117 $this->step = 5; 118 $this->post_offset = !empty($_REQUEST['offset']) ? abs((integer) $_REQUEST['offset']) : 0; 119 if ($this->importPosts($percent) === -1) { 120 http::redirect($this->getURL() . '&do=ok'); 121 } else { 122 echo $this->progressBar(ceil($percent * 0.93) + 7); 123 } 124 break; 125 case 'ok': 126 $this->resetVars(); 127 $this->core->blog->triggerBlog(); 128 $this->step = 6; 129 echo $this->progressBar(100); 130 break; 131 } 132 } 133 134 public function gui() 135 { 136 try { 137 $this->guiprocess($this->action); 138 } catch (Exception $e) { 139 $this->error($e); 140 } 141 142 # db drivers 143 $db_drivers = array( 144 'mysql' => 'mysql', 145 'mysqli' => 'mysqli' 146 ); 147 148 switch ($this->step) { 149 case 1: 150 echo 151 '<p>' . sprintf(__('Import the content of a Dotclear 1.2\'s blog in the current blog: %s.'), 152 '<strong>' . html::escapeHTML($this->core->blog->name) . '</strong>') . '</p>' . 153 '<p class="warning">' . __('Please note that this process ' . 154 'will empty your categories, blogroll, entries and comments on the current blog.') . '</p>'; 155 156 printf($this->imForm(1, __('General information'), __('Import my blog now')), 157 '<p>' . __('We first need some information about your old Dotclear 1.2 installation.') . '</p>' . 158 '<p><label for="db_driver">' . __('Database driver (must be mysqli if PHP 7 or higher):') . '</label> ' . 159 form::combo('db_driver', $db_drivers, html::escapeHTML($this->vars['db_driver'])) . '</p>' . 160 '<p><label for="db_host">' . __('Database Host Name:') . '</label> ' . 161 form::field('db_host', 30, 255, html::escapeHTML($this->vars['db_host'])) . '</p>' . 162 '<p><label for="db_name">' . __('Database Name:', html::escapeHTML($this->vars['db_name'])) . '</label> ' . 163 form::field('db_name', 30, 255, html::escapeHTML($this->vars['db_name'])) . '</p>' . 164 '<p><label for="db_user">' . __('Database User Name:') . '</label> ' . 165 form::field('db_user', 30, 255, html::escapeHTML($this->vars['db_user'])) . '</p>' . 166 '<p><label for="db_pwd">' . __('Database Password:') . '</label> ' . 167 form::password('db_pwd', 30, 255) . '</p>' . 168 '<p><label for="db_prefix">' . __('Database Tables Prefix:') . '</label> ' . 169 form::field('db_prefix', 30, 255, html::escapeHTML($this->vars['db_prefix'])) . '</p>' . 170 '<h3 class="vertical-separator">' . __('Entries import options') . '</h3>' . 171 '<p><label for="post_limit">' . __('Number of entries to import at once:') . '</label> ' . 172 form::number('post_limit', 0, 999, html::escapeHTML($this->vars['post_limit'])) . '</p>' 173 ); 174 break; 175 case 2: 176 printf($this->imForm(2, __('Importing users')), 177 $this->autoSubmit() 178 ); 179 break; 180 case 3: 181 printf($this->imForm(3, __('Importing categories')), 182 $this->autoSubmit() 183 ); 184 break; 185 case 4: 186 printf($this->imForm(4, __('Importing blogroll')), 187 $this->autoSubmit() 188 ); 189 break; 190 case 5: 191 $t = sprintf(__('Importing entries from %d to %d / %d'), $this->post_offset, 192 min(array($this->post_offset + $this->post_limit, $this->post_count)), $this->post_count); 193 printf($this->imForm(5, $t), 194 form::hidden(array('offset'), $this->post_offset) . 195 $this->autoSubmit() 196 ); 197 break; 198 case 6: 199 echo 200 '<h3 class="vertical-separator">' . __('Please read carefully') . '</h3>' . 201 '<ul>' . 202 '<li>' . __('Every newly imported user has received a random password ' . 203 'and will need to ask for a new one by following the "I forgot my password" link on the login page ' . 204 '(Their registered email address has to be valid.)') . '</li>' . 205 206 '<li>' . sprintf(__('Please note that Dotclear 2 has a new URL layout. You can avoid broken ' . 207 'links by installing <a href="%s">DC1 redirect</a> plugin and activate it in your blog configuration.'), 208 'http://plugins.dotaddict.org/dc2/details/dc1redirect') . '</li>' . 209 '</ul>' . 210 211 $this->congratMessage(); 212 213 break; 214 } 215 } 216 217 # Simple form for step by step process 218 protected function imForm($step, $legend, $submit_value = null) 219 { 220 if (!$submit_value) { 221 $submit_value = __('next step') . ' >'; 222 } 223 224 return 225 '<form action="' . $this->getURL(true) . '" method="post">' . 226 '<h3 class="vertical-separator">' . $legend . '</h3>' . 227 '<div>' . $this->core->formNonce() . 228 form::hidden(array('do'), 'step' . $step) . 229 '%s' . '</div>' . 230 '<p class="vertical-separator"><input type="submit" value="' . $submit_value . '" /></p>' . 231 '<p class="form-note info">' . __('Depending on the size of your blog, it could take a few minutes.') . '</p>' . 232 '</form>'; 233 } 234 235 # Error display 236 protected function error($e) 237 { 238 echo '<div class="error"><strong>' . __('Errors:') . '</strong>' . 239 '<p>' . $e->getMessage() . '</p></div>'; 240 } 241 242 # Database init 243 protected function db() 244 { 245 $db = dbLayer::init($this->vars['db_driver'], $this->vars['db_host'], $this->vars['db_name'], $this->vars['db_user'], $this->vars['db_pwd']); 246 247 $rs = $db->select("SHOW TABLES LIKE '" . $this->vars['db_prefix'] . "%'"); 248 if ($rs->isEmpty()) { 249 throw new Exception(__('Dotclear tables not found')); 250 } 251 252 while ($rs->fetch()) { 253 $this->has_table[$rs->f(0)] = true; 254 } 255 256 # Set this to read data as they were written in Dotclear 1 257 try { 258 $db->execute('SET NAMES DEFAULT'); 259 } catch (Exception $e) {} 260 261 $db->execute('SET CHARACTER SET DEFAULT'); 262 $db->execute("SET COLLATION_CONNECTION = DEFAULT"); 263 $db->execute("SET COLLATION_SERVER = DEFAULT"); 264 $db->execute("SET CHARACTER_SET_SERVER = DEFAULT"); 265 $db->execute("SET CHARACTER_SET_DATABASE = DEFAULT"); 266 267 $this->post_count = $db->select( 268 'SELECT COUNT(post_id) FROM ' . $this->vars['db_prefix'] . 'post ' 269 )->f(0); 270 271 return $db; 272 } 273 274 protected function cleanStr($str) 275 { 276 return text::cleanUTF8(@text::toUTF8($str)); 277 } 278 279 # Users import 280 protected function importUsers() 281 { 282 $db = $this->db(); 283 $prefix = $this->vars['db_prefix']; 284 $rs = $db->select('SELECT * FROM ' . $prefix . 'user'); 285 286 try 287 { 288 $this->con->begin(); 289 290 while ($rs->fetch()) { 291 if (!$this->core->userExists($rs->user_id)) { 292 $cur = $this->con->openCursor($this->prefix . 'user'); 293 $cur->user_id = $rs->user_id; 294 $cur->user_name = $rs->user_nom; 295 $cur->user_firstname = $rs->user_prenom; 296 $cur->user_displayname = $rs->user_pseudo; 297 $cur->user_pwd = crypt::createPassword(); 298 $cur->user_email = $rs->user_email; 299 $cur->user_lang = $rs->user_lang; 300 $cur->user_tz = $this->core->blog->settings->system->blog_timezone; 301 $cur->user_post_status = $rs->user_post_pub ? 1 : -2; 302 $cur->user_options = new ArrayObject(array( 303 'edit_size' => (integer) $rs->user_edit_size, 304 'post_format' => $rs->user_post_format 305 )); 306 307 $permissions = array(); 308 switch ($rs->user_level) { 309 case '0': 310 $cur->user_status = 0; 311 break; 312 case '1': # editor 313 $permissions['usage'] = true; 314 break; 315 case '5': # advanced editor 316 $permissions['contentadmin'] = true; 317 $permissions['categories'] = true; 318 $permissions['media_admin'] = true; 319 break; 320 case '9': # admin 321 $permissions['admin'] = true; 322 break; 323 } 324 325 $this->core->addUser($cur); 326 $this->core->setUserBlogPermissions( 327 $rs->user_id, 328 $this->blog_id, 329 $permissions 330 ); 331 } 332 } 333 334 $this->con->commit(); 335 $db->close(); 336 } catch (Exception $e) { 337 $this->con->rollback(); 338 $db->close(); 339 throw $e; 340 } 341 } 342 343 # Categories import 344 protected function importCategories() 345 { 346 $db = $this->db(); 347 $prefix = $this->vars['db_prefix']; 348 $rs = $db->select('SELECT * FROM ' . $prefix . 'categorie ORDER BY cat_ord ASC'); 349 350 try 351 { 352 $this->con->execute( 353 'DELETE FROM ' . $this->prefix . 'category ' . 354 "WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' " 355 ); 356 357 $ord = 2; 358 while ($rs->fetch()) { 359 $cur = $this->con->openCursor($this->prefix . 'category'); 360 $cur->blog_id = $this->blog_id; 361 $cur->cat_title = $this->cleanStr(htmlspecialchars_decode($rs->cat_libelle)); 362 $cur->cat_desc = $this->cleanStr($rs->cat_desc); 363 $cur->cat_url = $this->cleanStr($rs->cat_libelle_url); 364 $cur->cat_lft = $ord++; 365 $cur->cat_rgt = $ord++; 366 367 $cur->cat_id = $this->con->select( 368 'SELECT MAX(cat_id) FROM ' . $this->prefix . 'category' 369 )->f(0) + 1; 370 $this->vars['cat_ids'][$rs->cat_id] = $cur->cat_id; 371 $cur->insert(); 372 } 373 374 $db->close(); 375 } catch (Exception $e) { 376 $db->close(); 377 throw $e; 378 } 379 } 380 381 # Blogroll import 382 protected function importLinks() 383 { 384 $db = $this->db(); 385 $prefix = $this->vars['db_prefix']; 386 $rs = $db->select('SELECT * FROM ' . $prefix . 'link ORDER BY link_id ASC'); 387 388 try 389 { 390 $this->con->execute( 391 'DELETE FROM ' . $this->prefix . 'link ' . 392 "WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' " 393 ); 394 395 while ($rs->fetch()) { 396 $cur = $this->con->openCursor($this->prefix . 'link'); 397 $cur->blog_id = $this->blog_id; 398 $cur->link_href = $this->cleanStr($rs->href); 399 $cur->link_title = $this->cleanStr($rs->label); 400 $cur->link_desc = $this->cleanStr($rs->title); 401 $cur->link_lang = $this->cleanStr($rs->lang); 402 $cur->link_xfn = $this->cleanStr($rs->rel); 403 $cur->link_position = (integer) $rs->position; 404 405 $cur->link_id = $this->con->select( 406 'SELECT MAX(link_id) FROM ' . $this->prefix . 'link' 407 )->f(0) + 1; 408 $cur->insert(); 409 } 410 411 $db->close(); 412 } catch (Exception $e) { 413 $db->close(); 414 throw $e; 415 } 416 } 417 418 # Entries import 419 protected function importPosts(&$percent) 420 { 421 $db = $this->db(); 422 $prefix = $this->vars['db_prefix']; 423 424 $count = $db->select('SELECT COUNT(post_id) FROM ' . $prefix . 'post')->f(0); 425 426 $rs = $db->select( 427 'SELECT * FROM ' . $prefix . 'post ORDER BY post_id ASC ' . 428 $db->limit($this->post_offset, $this->post_limit) 429 ); 430 431 try 432 { 433 if ($this->post_offset == 0) { 434 $this->con->execute( 435 'DELETE FROM ' . $this->prefix . 'post ' . 436 "WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' " 437 ); 438 } 439 440 while ($rs->fetch()) { 441 $this->importPost($rs, $db); 442 } 443 444 $db->close(); 445 } catch (Exception $e) { 446 $db->close(); 447 throw $e; 448 } 449 450 if ($rs->count() < $this->post_limit) { 451 return -1; 452 } else { 453 $this->post_offset += $this->post_limit; 454 } 455 456 if ($this->post_offset > $this->post_count) { 457 $percent = 100; 458 } else { 459 $percent = $this->post_offset * 100 / $this->post_count; 460 } 461 } 462 463 protected function importPost($rs, $db) 464 { 465 $cur = $this->con->openCursor($this->prefix . 'post'); 466 $cur->blog_id = $this->blog_id; 467 $cur->user_id = $rs->user_id; 468 $cur->cat_id = (integer) $this->vars['cat_ids'][$rs->cat_id]; 469 $cur->post_dt = $rs->post_dt; 470 $cur->post_creadt = $rs->post_creadt; 471 $cur->post_upddt = $rs->post_upddt; 472 $cur->post_title = html::decodeEntities($this->cleanStr($rs->post_titre)); 473 474 $cur->post_url = date('Y/m/d/', strtotime($cur->post_dt)) . $rs->post_id . '-' . $rs->post_titre_url; 475 $cur->post_url = substr($cur->post_url, 0, 255); 476 477 $cur->post_format = $rs->post_content_wiki == '' ? 'xhtml' : 'wiki'; 478 $cur->post_content_xhtml = $this->cleanStr($rs->post_content); 479 $cur->post_excerpt_xhtml = $this->cleanStr($rs->post_chapo); 480 481 if ($cur->post_format == 'wiki') { 482 $cur->post_content = $this->cleanStr($rs->post_content_wiki); 483 $cur->post_excerpt = $this->cleanStr($rs->post_chapo_wiki); 484 } else { 485 $cur->post_content = $this->cleanStr($rs->post_content); 486 $cur->post_excerpt = $this->cleanStr($rs->post_chapo); 487 } 488 489 $cur->post_notes = $this->cleanStr($rs->post_notes); 490 $cur->post_status = (integer) $rs->post_pub; 491 $cur->post_selected = (integer) $rs->post_selected; 492 $cur->post_open_comment = (integer) $rs->post_open_comment; 493 $cur->post_open_tb = (integer) $rs->post_open_tb; 494 $cur->post_lang = $rs->post_lang; 495 496 $cur->post_words = implode(' ', text::splitWords( 497 $cur->post_title . ' ' . 498 $cur->post_excerpt_xhtml . ' ' . 499 $cur->post_content_xhtml 500 )); 501 502 $cur->post_id = $this->con->select( 503 'SELECT MAX(post_id) FROM ' . $this->prefix . 'post' 504 )->f(0) + 1; 505 506 $cur->insert(); 507 $this->importComments($rs->post_id, $cur->post_id, $db); 508 $this->importPings($rs->post_id, $cur->post_id, $db); 509 510 # Load meta if we have some in DC1 511 if (isset($this->has_table[$this->vars['db_prefix'] . 'post_meta'])) { 512 $this->importMeta($rs->post_id, $cur->post_id, $db); 513 } 514 } 515 516 # Comments import 517 protected function importComments($post_id, $new_post_id, $db) 518 { 519 $count_c = $count_t = 0; 520 521 $rs = $db->select( 522 'SELECT * FROM ' . $this->vars['db_prefix'] . 'comment ' . 523 'WHERE post_id = ' . (integer) $post_id . ' ' 524 ); 525 526 while ($rs->fetch()) { 527 $cur = $this->con->openCursor($this->prefix . 'comment'); 528 $cur->post_id = (integer) $new_post_id; 529 $cur->comment_author = $this->cleanStr($rs->comment_auteur); 530 $cur->comment_status = (integer) $rs->comment_pub; 531 $cur->comment_dt = $rs->comment_dt; 532 $cur->comment_upddt = $rs->comment_upddt; 533 $cur->comment_email = $this->cleanStr($rs->comment_email); 534 $cur->comment_content = $this->cleanStr($rs->comment_content); 535 $cur->comment_ip = $rs->comment_ip; 536 $cur->comment_trackback = (integer) $rs->comment_trackback; 537 538 $cur->comment_site = $this->cleanStr($rs->comment_site); 539 if ($cur->comment_site != '' && !preg_match('!^http://.*$!', $cur->comment_site)) { 540 $cur->comment_site = substr('http://' . $cur->comment_site, 0, 255); 541 } 542 543 if ($rs->exists('spam') && $rs->spam && $rs->comment_status = 0) { 544 $cur->comment_status = -2; 545 } 546 547 $cur->comment_words = implode(' ', text::splitWords($cur->comment_content)); 548 549 $cur->comment_id = $this->con->select( 550 'SELECT MAX(comment_id) FROM ' . $this->prefix . 'comment' 551 )->f(0) + 1; 552 553 $cur->insert(); 554 555 if ($cur->comment_trackback && $cur->comment_status == 1) { 556 $count_t++; 557 } elseif ($cur->comment_status == 1) { 558 $count_c++; 559 } 560 } 561 562 if ($count_t > 0 || $count_c > 0) { 563 $this->con->execute( 564 'UPDATE ' . $this->prefix . 'post SET ' . 565 'nb_comment = ' . $count_c . ', ' . 566 'nb_trackback = ' . $count_t . ' ' . 567 'WHERE post_id = ' . (integer) $new_post_id . ' ' 568 ); 569 } 570 } 571 572 # Pings import 573 protected function importPings($post_id, $new_post_id, $db) 574 { 575 $urls = array(); 576 577 $rs = $db->select( 578 'SELECT * FROM ' . $this->vars['db_prefix'] . 'ping ' . 579 'WHERE post_id = ' . (integer) $post_id 580 ); 581 582 while ($rs->fetch()) { 583 $url = $this->cleanStr($rs->ping_url); 584 if (isset($urls[$url])) { 585 continue; 586 } 587 588 $cur = $this->con->openCursor($this->prefix . 'ping'); 589 $cur->post_id = (integer) $new_post_id; 590 $cur->ping_url = $url; 591 $cur->ping_dt = $rs->ping_dt; 592 $cur->insert(); 593 594 $urls[$url] = true; 595 } 596 } 597 598 # Meta import 599 protected function importMeta($post_id, $new_post_id, $db) 600 { 601 $rs = $db->select( 602 'SELECT * FROM ' . $this->vars['db_prefix'] . 'post_meta ' . 603 'WHERE post_id = ' . (integer) $post_id . ' ' 604 ); 605 606 if ($rs->isEmpty()) { 607 return; 608 } 609 610 while ($rs->fetch()) { 611 $this->core->meta->setPostMeta($new_post_id, $this->cleanStr($rs->meta_key), $this->cleanStr($rs->meta_value)); 612 } 613 } 633 614 }
Note: See TracChangeset
for help on using the changeset viewer.