Dotclear

source: plugins/importExport/inc/class.dc.import.dc1.php @ 3572:7b171ccd8cee

Revision 3572:7b171ccd8cee, 17.5 KB checked in by franck <carnet.franck.paul@…>, 8 years ago (diff)

Reduce indexed varchar(255) fields to varchar(191) : table category, field cat_url; table dc_meta, field meta_id; table dc_ping, field ping_url; table dc_post, field post_url; table dc_pref, field pref_id; table dc_setting, field setting_id. Addresses #1278

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of importExport, a plugin for DotClear2.
5#
6# Copyright (c) 2003-2012 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12if (!defined('DC_RC_PATH')) { return; }
13
14class dcImportDC1 extends dcIeModule
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,191);
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     }
633}
Note: See TracBrowser for help on using the repository browser.

Sites map