Dotclear

source: plugins/importExport/inc/class.dc.import.dc1.php @ 3725:b47f38c701ee

Revision 3725:b47f38c701ee, 22.5 KB checked in by franck <carnet.franck.paul@…>, 7 years ago (diff)

Use specialized input fields (color, email, url, number, …) where is relevant

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            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    }
614}
Note: See TracBrowser for help on using the repository browser.

Sites map