Make WordPress Core

Ticket #4611: flatimport.php

File flatimport.php, 41.4 KB (added by albaran, 18 years ago)

"Dotclear flatimport": import for Dotclear 2 or 1 from file

Line 
1<?php
2/*_____________________________________________________________________________
3The flatimport importer is based on the Dotclear importer (itself from the Textpattern importer)
4and the Dotclear 2 importexport plugin.
5Import Dotclear 1.2.x or Dotclear 2.0-beta into WordPress 2.3
6Initial version: november 2006 ; WP2.3 version: july 2007.
7Forum: http://www.wordpress-fr.net/support/sujet-2944-import-dotclear-fichier-texte
8_____________________________________________________________________________*/
9if ( @ini_get('max_execution_time') == 50000 ) {
10        @ini_set('max_execution_time', 38); # try to modify the max_execution_time for 1and1 50000 seconds
11} elseif ( @ini_get('max_execution_time') < 1200 ) {
12        @ini_set('max_execution_time', 1200); # try to modify the max_execution_time ; Free.fr 20 or 30 seconds
13}
14/** The Main Importer Class **/
15class Flat_Import {
16
17        function import_flat_file() {
18                global $wpdb, $utw, $STagging, $STaggingAdmin, $fi_import_format, $fi_dc_tables, $fi_dc_cats, $fi_dcposts2wpposts, $fi_linkcat_pos, $fi_linkcat_link_id, $fi_link_pos, $fi_link_link_id, $fi_dcid2wpid, $post_old_strings, $post_new_strings, $wp_version, $fi_update_mode;
19
20                $flatimport_version = '2.3.0.1'; # pour WP 2.3 13:53 01/08/2007
21                $time_start = time();
22               
23                $table_recover_count = 20; # a point of control is taken after importing the following number of values for a given table
24                $time_to_reload = 1; # number of seconds to substract from max_execution_time to have the timeout to reload the current page
25
26                $max_execution_time = @ini_get('max_execution_time'); # usually 30 seconds, Free.fr 20 or 30 ; 1and1 50000
27                /*_____________________________________________________________________________
28                allow automatic recovery by setting the $max_execution_time variable
29                uncomment the following line to force the timeout
30                set the value to 38 for 1and1 server ; or other appropriate value
31                _____________________________________________________________________________*/
32                #$max_execution_time = 30;
33
34                $automatic_recovery = false;
35                if ( is_numeric($max_execution_time) ) { # validate if the server return a positive number
36                        if ($max_execution_time > 3) { # to control lower values: do not handle by automatic recovery a max_execution_time lower than this value
37                                $automatic_recovery = true;
38                        }
39                        if ($max_execution_time < 0) {
40                                $max_execution_time = NULL;
41                        }
42                } else {
43                        $max_execution_time = NULL;
44                }
45                /*_____________________________________________________________________________
46                comment/uncomment the following line to enable/disable the automatic recovery feature.
47                The user must click on the displayed Continue button to proceed if disabled
48                _____________________________________________________________________________*/
49                #$automatic_recovery = false;
50               
51                $post_old_strings = array();
52                $post_new_strings = array();
53                if ( file_exists(dirname(__FILE__).'/../../wp-content/uploads/blog-backup-change.php') )
54                        include_once(dirname(__FILE__).'/../../wp-content/uploads/blog-backup-change.php');
55                $fi_filename = dirname(__FILE__).'/../../wp-content/uploads/blog-backup.txt';
56                $post_id_filename = dirname(__FILE__).'/../../wp-content/uploads/post_id_dc2wp.php';
57                $fi_import_format = '';
58                $fi_recover_filename = dirname(__FILE__).'/../../wp-content/uploads/blog-backup-recovery.txt';
59                $fi_recover_mode = false;
60                $recover_names = array(
61                        'fi_filename_size',
62                        'fi_file_pointer',
63                        'fi_dc_tables',
64                        'fi_dc_cats',
65                        'fi_dcposts2wpposts',
66                        'fi_table_cols',
67                        'fi_linkcat_pos',
68                        'fi_linkcat_link_id',
69                        'fi_link_pos',
70                        'fi_link_link_id',
71                        'fi_dcid2wpid',
72                        'fi_table_name',
73                        'fi_table_name_found',
74                        'fi_table_import',
75                        'fi_update_mode'
76                        );
77                $dc_version = '';
78                $replacement = array(
79                '\n' => "\n",
80                '\r' => "\r",
81                '\"' => '"'
82                );
83                # Default link category
84                $wp_def_link_category_name = __('Blogroll');
85                $deflinkcat = is_term( $wp_def_link_category_name, 'link_category' );
86                if ($deflinkcat) {
87                        $wp_def_link_category_id = $deflinkcat['term_id'];
88                } else {
89                        $wp_def_link_category_id = Flat_Import::wp_create_link_category($wp_def_link_category_name);
90                }
91               
92                if ( file_exists($fi_recover_filename) ) {
93                        if ( filesize($fi_recover_filename) > 0) {
94                                # test for a non empty point of control file (uses dynamic variables $$name and serialyse unserialyse), if yes proceed to recovery
95                                $fi_recover = @fopen($fi_recover_filename, "r");
96                                if ($fi_recover) {
97                                        while (!feof($fi_recover)) {
98                                                $serialized_line = fgets($fi_recover);
99                                                $name_recover = trim(substr($serialized_line, 0, strpos($serialized_line, ' ')));
100                                                $$name_recover = unserialize(trim(substr($serialized_line, strpos($serialized_line, ' '))));
101                                        }
102                                        fclose($fi_recover);
103                                        /* dump recover vars
104                                        foreach ($recover_names as $value) {
105                                                echo '<pre>';
106                                                print_r($$value);
107                                                echo '</pre>';
108                                                echo '<hr />';
109                                        }
110                                        # */
111                                        $fi_recover_mode = true;
112                                        # vérif des variables en recovery
113                                        foreach ($recover_names as $value) {
114                                                if ( !isset($$value) ) $fi_recover_mode = false;
115                                        }
116                                        if ( $fi_recover_mode ) {
117                                                # check that the recovery data applies to the backup file
118                                                if ( $fi_filename_size != filesize($fi_filename) ) $fi_recover_mode = false;
119                                        }
120                                        if ( $fi_recover_mode ) {
121                                                $count = $fi_dc_tables[$fi_table_name] + $table_recover_count; # reinitialize count
122                                        } else {
123                                                $import_mode_str = ($fi_update_mode) ? ('<strong>'.__('Update').'</strong>') : ('<strong>'.__('Import').'</strong>');
124                                                echo '<p><strong>'.__('Warning:').'</strong> '.__('Non valid blog-backup-recovery.txt').' ; '.__('switching to').' '.$import_mode_str.'</p>';
125                                        }
126                                }
127                        }
128                }
129                if ( !$fi_recover_mode ) {
130                        $fi_dc_tables = array(
131                                'setting' => 0,
132                                'user' => 0,
133                                'categorie' => 0,
134                                'category' => 0,
135                                'link' => 0,
136                                'post' => 0,
137                                'comment' => 0,
138                                'meta' => 0,
139                                'post_meta' => 0,
140                                'blog' => 0,
141                                'media' => 0,
142                                'version' => 0
143                                );
144                        # categories dc ; nécessaires pour import des posts ; pour dc : id nom
145                        $fi_dc_cats = array(); # id du cat dc => id de cat wp
146                        # association des commentaires aux billets (tableau de correspondance des IDs, table de translation des post_id dc en ID WP)
147                        $fi_dcposts2wpposts = array(); # table de translation des post_id dc en ID WP
148                        # association des liens à leur catégorie par position
149                        $fi_linkcat_pos = array(); # on associe au cat_id ds wp_linkcategories la position dc
150                        $fi_linkcat_link_id = array(); # on associe au cat_id ds wp_linkcategories le link_id dc
151                        $fi_link_pos = array(); # on associe au link_id ds wp_links la position dc
152                        $fi_link_link_id = array(); # on associe au cat_id ds wp_linkcategories le link_id dc
153                        $fi_dcid2wpid = array(); # key: dc user_id (admin) => value: wp ID (1)
154                        $fi_table_name = '';
155                        $fi_table_name_found = array();
156                        $fi_table_import = false;
157                }
158               
159                $backup = @fopen($fi_filename, "r");
160                if ($backup)
161                {
162                        $first_line = fgets($backup);
163                       
164                        if (strpos($first_line,'///DOTCLEAR|') === false) { # accepte fichier UTF8 avec ou sans BOM
165                                echo __('File is not a DotClear backup.');
166                                return;
167                        }
168                       
169                        $l = explode('|',$first_line);
170                       
171                        if (isset($l[1])) {
172                                $dc_version = $l[1];
173                        }
174                        /*
175                        $mode = isset($l[2]) ? strtolower(trim($l[2])) : 'single';
176                        if ($mode != 'full' && $mode != 'single') {
177                                $mode = 'single';
178                        }
179                        # */
180                        $fi_import_format = substr($dc_version, 0 ,3);
181                       
182                        if ( ($fi_import_format == '1.2') OR ($fi_import_format == '2.0') ) {
183                                $import_mode_str = ($fi_update_mode) ? ('<strong>'.__('Update').'</strong>') : ('<strong>'.__('Import').'</strong>');
184                                $auto_str = $automatic_recovery ? (__('Automatic recovery')) : ('<strong>'.__('No automatic recovery').'</strong>');
185                                $timeout_str = is_null($max_execution_time) ? '' : (__('Timeout').': '.$max_execution_time.' '.__('seconds'));
186                                Flat_Import::say('Version: '.$flatimport_version.' - '.$import_mode_str.' '.__('from Dotclear version').' <strong>'.$dc_version.
187                                '</strong> to WordPress <strong>'.get_bloginfo('version').
188                                '</strong> - '.__('data base formats').': dc '.$fi_import_format.' - '.
189                                $auto_str.' - '.$timeout_str.'<br />');
190                        } else {
191                                echo __('Unknown version of Dotclear for import file.').' - '.$first_line.' - '.$dc_version.' - '.$fi_import_format.'<br />';
192                                return;
193                        }
194                        /*_____________________________________________________________________________
195                        Recovery mode
196                        _____________________________________________________________________________*/
197                        if ($fi_recover_mode) { # the script was interrupted by the server ; retry from the last point of control taken
198                                fseek($backup, $fi_file_pointer);
199                                Flat_Import::say('<strong>'.__('Entering recovery mode').'</strong> '.__('from the pointer position:').
200                                ' <strong>'.number_format($fi_file_pointer, 0, ',', ' ').'</strong> - '.
201                                Flat_Import::filesize_format($fi_file_pointer).'<br />');
202                        }
203                        /*_____________________________________________________________________________
204                        Read each entry in blog-backup and proceed
205                        _____________________________________________________________________________*/
206                        while (!feof($backup))
207                        {
208                                $line = trim(fgets($backup));
209                               
210                                if (substr($line,0,1) == '[') { # importation d'une table : le nom de la table est suivi des noms de champs
211                                        if ( $fi_table_import AND ($fi_table_name != '') AND ($fi_dc_tables[$fi_table_name] > 0) ) {
212                                        # affichage de fin d'import d'une table et du nombre d'éléments traités
213                                                Flat_Import::say('<strong>'.__('Import of').' '.$fi_table_name.' : '.$fi_dc_tables[$fi_table_name].'</strong>');
214                                        }
215                                       
216                                        $count = $table_recover_count; # new table : init count to do a point of control and and display an user message every 20 values for a table
217                                       
218                                        $fi_table_name = substr($line,1,strpos($line,' ')-1);
219                                        Flat_Import::say('<em>'.__('Working with table:').' '.$fi_table_name.'</em>');
220                                        $line = substr($line,strpos($line,' ')+1,-1);
221                                        $fi_table_cols = explode(',',$line);
222                                        $fi_table_import = true;
223                                        if (array_key_exists($fi_table_name, $fi_dc_tables)) {
224                                                $fi_table_name_found[] = $fi_table_name;
225                                                # conditions d'import et de précédence des tables
226                                                if ( ($fi_table_name == 'post_meta') OR ($fi_table_name == 'meta') ) {
227                                                        if ( in_array('post', $fi_table_name_found) ) {
228                                                                Flat_Import::say('<em>'.__('Importing tags').'</em>');
229                                                        } else {
230                                                                $fi_table_import = false;
231                                                                Flat_Import::say('<strong>'.__('Error:').'</strong> '.__('No import of tags. No posts found.'));
232                                                        }
233                                                }
234                                                if ($fi_table_name == 'comment') {
235                                                        if ( !in_array('post', $fi_table_name_found) ) {
236                                                                $fi_table_import = false;
237                                                                Flat_Import::say('<strong>'.__('Error:').'</strong> '.__('No import of comments. No posts found.'));
238                                                        }
239                                                }
240                                                if ($fi_table_name == 'post') {
241                                                        $post_import_msg = true;
242                                                        if (!( ( in_array('categorie', $fi_table_name_found) ) OR ( in_array('category', $fi_table_name_found) ) )) {
243                                                                $post_import_msg = false;
244                                                                Flat_Import::say('<strong>'.__('Warning:').'</strong> '.__('No categories found. All posts associated to the ID 1 category'));
245                                                        }
246                                                        if ( !( in_array('user', $fi_table_name_found) ) ) {
247                                                                Flat_Import::say('<strong>'.__('Warning:').'</strong> '.__('No users found. All posts associated to admin'));
248                                                        }
249                                                }
250                                        } else {
251                                                echo __('No import for table').' <strong>'.$fi_table_name.'</strong><br />';
252                                                $fi_table_import = false;
253                                        }
254                                } elseif (substr($line,0,1) == '"') { # importation des valeurs d'une table
255                                        if ($fi_table_import) {
256                                                if (array_key_exists($fi_table_name, $fi_dc_tables)) {
257                                                        $line1 = preg_replace('/^"|"$/','',$line);
258                                                        $line_split = preg_split('/(^"|","|"$)/m',$line1);
259                                                       
260                                                        if (count($fi_table_cols) != count($line_split)) {
261                                                                echo __('Import of').' '.$fi_table_name.': invalid row count'.' - '.htmlspecialchars($line).'<br />';
262                                                        } else {
263                                                                #Flat_Import::say(substr($line,0,100).'&hellip;'.'|'.$fi_dc_tables[$fi_table_name].'|'.$count.'|'.'<br />');
264                                                        }
265                                                        $res = array();
266                                                        for ($i=0; $i<count($line_split); $i++) {
267                                                                $res[$fi_table_cols[$i]] =
268                                                                str_replace(array_keys($replacement),array_values($replacement),$line_split[$i]);
269                                                        }
270                                                        call_user_func(array('Flat_Import', $fi_table_name), $res); # appel des fonctions d'import, import des valeurs d'une entrée de table
271                                                       
272                                                        # message and point of control every 20 table values ( value of $table_recover_count) or timeout reached
273                                                        if ( is_null($max_execution_time) ) {
274                                                                $exec_time_left = 1; # set it for a positive value so we will never reload the current page
275                                                                $exec_time_left_str = '';
276                                                        } else {
277                                                                $exec_time_now = time()- $time_start;
278                                                                $exec_time_left = ($max_execution_time - $time_to_reload) - $exec_time_now;
279                                                                $exec_time_left_str = '+'.$exec_time_now.' - '.$exec_time_left.' '.__('seconds left');
280                                                        }
281                                                        if ( ($fi_dc_tables[$fi_table_name] == $count) OR ($exec_time_left <= 0) ) {
282                                                                $count = $count + $table_recover_count;
283                                                               
284                                                                Flat_Import::say(__('Import of').' '.$fi_table_name.' : '.$fi_dc_tables[$fi_table_name].'&hellip;'.$exec_time_left_str);
285                                                               
286                                                                # take a point of control ; for blog-backup.txt : size to check the right file, pointeur position, then needed variables
287                                                                # serialize() arrays, vars and save them to be able to recover an interrupted import ; uses dynamic variables
288                                                               
289                                                                # delete the backup of the recovery file ; then backup it ; to allow manual recovery if the following code is interrupted
290                                                                if ( file_exists($fi_recover_filename.'.bak') ) unlink($fi_recover_filename.'.bak');
291                                                                if ( file_exists($fi_recover_filename) ) rename($fi_recover_filename, $fi_recover_filename.'.bak');
292                                                               
293                                                                $fi_filename_size = filesize($fi_filename); # to check file at recovery time
294                                                                $fi_file_pointer = ftell($backup); # take the current pointer position
295                                                                $fi_recover = fopen($fi_recover_filename, 'wb'); # open and create or empty the recovery file
296                                                                foreach ($recover_names as $value) {
297                                                                        fwrite($fi_recover, $value.' '.serialize($$value)."\r\n"); # output serialysed vars
298                                                                }
299                                                                fclose($fi_recover);
300                                                               
301                                                                # reload the current page if timeout reached either by meta refresh or by clic on the Continue button
302                                                                # cannot use register_shutdown_function(): one cannot send any HTTP header in the shutdown callback
303                                                                # When zlib compression is enabled, register_shutdown_function doesn't work properly.
304                                                                # Anything output from your shutdown function will not be readable by the browser. Firefox just ignores it. IE6 will show you a blank page.
305                                                                if ($exec_time_left <= 0) {
306                                                                        $recover_step = ($fi_update_mode) ? 2 : 1; # Update : Import
307                                                                        $import_mode_str = ($fi_update_mode) ? ('<strong>'.__('Update').'</strong>') : ('<strong>'.__('Import').'</strong>');
308                                                                        echo '<form action="admin.php?import=flatimport&amp;step='.$recover_step.'" method="post">';
309                                                                        wp_nonce_field('import-flatimport');
310                                                                        echo '<input type="submit" name="submit" value="'.attribute_escape(__('Continue')).'" />';
311                                                                        echo ' '.__('Click on the <strong>Continue</strong> button to continue the').
312                                                                        ' '.$import_mode_str.' '.__('<em>(by reloading the page to reset the timeout)</em>').'.';
313                                                                        echo '</form>';
314                                                                       
315                                                                        if ($automatic_recovery) {
316                                                                                /*
317                                                                                We want to avoid any  message like: Warning: the page you are refreshing contains POST data... with a mandatory click needed.
318                                                                                This is the case here for PHP header(Location: ... and JavaScript location.reload() ; some remaining blanks characters or others not found.
319                                                                               
320                                                                                META refresh is deprecated by W3C ; should not be used for redirecting to a new address (this is not the case here).
321                                                                                Reloading the current page using meta refresh works for Firefox 2 and IE7.
322                                                                               
323                                                                                Do the meta refresh, it won't resend the data, 0 is the time in seconds, reload the current page as the url is omitted.
324                                                                                The user will use the Continue button if the meta refresh is not granted by the navigator or the server.
325                                                                                */
326                                                                                echo Flat_Import::wp_nonce_meta_refresh('import-flatimport', 'admin.php?import=flatimport&step=3'); # do the meta refresh
327                                                                        }
328                                                                        # terminate
329                                                                        fclose($backup);
330                                                                        ob_flush();flush(); # send all
331                                                                        exit; # end the execution of this script
332                                                                }
333                                                        }
334                                                }
335                                        }
336                                } else {
337                                        if ($line != '') {
338                                                if (strlen($line) > 100) $line = substr($line,0,100).'&hellip;';
339                                                echo __('Unknown line').' <i>'.htmlspecialchars($line).'</i><br />';
340                                        }
341                                }
342                        }
343                        fclose($backup);
344                        if ( ($fi_table_name != '') AND ($fi_dc_tables[$fi_table_name] > 0) )
345                                echo '<strong>'.__('Import of').' '.$fi_table_name.' : '.$fi_dc_tables[$fi_table_name].'</strong><br />';
346                        /*_____________________________________________________________________________
347                        Associate links to link categories
348                        must be done here in post-processing due to the positional structure of the dc link table
349                        _____________________________________________________________________________*/
350                        if ( (count($fi_linkcat_pos)>0) AND (count($fi_link_pos)>0) ) {
351                                # associate links to cat based on dc position OR link_id if all dc positions at zero
352                                # $fi_linkcat_pos associe au cat_id ds wp_categories la position dc
353                                # $fi_linkcat_link_id associe au cat_id ds wp_categories le link_id dc
354                                # $fi_link_pos associe au link_id ds wp_links la position dc
355                                # $fi_link_link_id associe au link_id ds wp_links le link_id dc
356                                $link_pos_cumul = eval('return ' . implode('+', $fi_link_pos) . ';');
357                                if ($link_pos_cumul == 0) { # on prend le link_id si les positions sont à zéro
358                                        $fi_linkcat_pos = $fi_linkcat_link_id;
359                                        $fi_link_pos = $fi_link_link_id;
360                                }
361                                asort($fi_linkcat_pos); # tri les cat de liens par ordre croissant pour comparaison
362                                echo '<em>'.__('Associate links to link categories.').'</em>'.'<br />';
363                                foreach ($fi_link_pos as $_id => $_pos) { # pour chaque lien
364                                        $link_cat = false;
365                                        foreach ($fi_linkcat_pos as $_catid => $_catpos) {
366                                                if ($_pos > $_catpos) {
367                                                        $link_cat = $_catid; # recherche d'une cat de lien en position avant celle du lien
368                                                }
369                                        }
370                                        if ($link_cat === false) {
371                                                $link_cat = $wp_def_link_category_id;
372                                                echo __('Orphan link').' '.$_id.' - '.__('associated to default link category').' '.$wp_def_link_category_name.'<br />';
373                                        }
374                                        $ret_id = wp_set_link_cats($_id, array($link_cat));
375                                }
376                        }
377                        /*_____________________________________________________________________________
378                        Import post-processing
379                        _____________________________________________________________________________*/
380                        /*
381                        # on archive la table de translation des post_id dc en ID WP ;  $fi_dcposts2wpposts
382                        $post_id_dc2wp = fopen($post_id_filename, 'wb'); # open and create or empty the file
383                        fwrite($post_id_dc2wp, '<?php'."\r\n".'$post_old_strings = array('."\r\n");
384                        foreach ($fi_dcposts2wpposts as $key => $value) {
385                                fwrite($post_id_dc2wp, "'url_dc".$key."',"."\r\n");
386                        }
387                        fwrite($post_id_dc2wp, ');'."\r\n".'$post_new_strings = array('."\r\n");
388                        foreach ($fi_dcposts2wpposts as $key => $value) {
389                                fwrite($post_id_dc2wp, "'url_wp".$value."',"."\r\n");
390                        }
391                        fwrite($post_id_dc2wp, ');'."\r\n".'?>'."\r\n");
392                        fclose($post_id_dc2wp);
393                        #*/
394                        if ( file_exists($fi_recover_filename) ) unlink($fi_recover_filename);
395                       
396                        echo ' <strong>'.__('End of import').'.</strong>'.' '.
397                        __('Read carefully the following page').'. '.__('Hit the finish button').'<br />';
398                        echo '<form action="admin.php?import=flatimport&amp;step=4" method="post">';
399                        wp_nonce_field('import-flatimport');
400                        echo '<p><input type="submit" name="submit" value="'.attribute_escape(__('Finish')).'" /></p>';
401                        echo '</form>';
402                        # End of import post-processing
403                } else {
404                        echo '<p><strong>'.__('Warning:').'</strong> '.__('No import file found').
405                        ' <em>wp-content/uploads/blog-backup.txt</em></p>'.'<p>'.__('Unable to open:').' '.$fi_filename.'</p>';
406                }
407        }
408        /*_____________________________________________________________________________
409                Processing of table entries
410        _____________________________________________________________________________*/
411        function blog($blog) {
412                global $wpdb, $fi_import_format, $fi_dc_tables;
413                # nop
414        }
415       
416        function setting($setting) {
417                global $wpdb, $fi_import_format, $fi_dc_tables;
418                # nop
419        }
420       
421        function media($media) {
422                global $wpdb, $fi_import_format, $fi_dc_tables;
423                # nop
424        }
425       
426        function version($version) {
427                global $wpdb, $fi_import_format, $fi_dc_tables;
428                # nop
429        }
430
431        function category($category) {
432                Flat_Import::categorie($category, 'category');
433        }
434        function categorie($category, $fi_table_name='categorie') {
435                global $wpdb, $fi_dc_cats, $fi_import_format, $fi_dc_tables, $fi_update_mode;
436               
437                extract($category);
438                // Make Nice Variables
439                if ($fi_import_format == '2.0') {
440                        $cat_libelle = $cat_title;
441                        $cat_libelle_url = $cat_url;
442                }
443                $name = $wpdb->escape($cat_libelle_url);
444                $title = $wpdb->escape($cat_libelle);
445                $desc = $wpdb->escape($cat_desc);
446               
447                if($cinfo = category_exists($name)) {
448                        if ($fi_update_mode) {
449                                $wp_cat_id = wp_update_category(array(
450                                        'cat_ID' => $cinfo,
451                                        'category_nicename' => $name,
452                                        'cat_name' => addslashes($title),
453                                        'category_description' => $desc
454                                        ));
455                                $fi_dc_tables[$fi_table_name]++;
456                        } else {
457                                $wp_cat_id = $cinfo;
458                        }
459                } else {
460                        $wp_cat_id = wp_insert_category(array(
461                                'category_nicename' => $name,
462                                'cat_name' => addslashes($title),
463                                'category_description' => $desc
464                                ));
465                        $fi_dc_tables[$fi_table_name]++;
466                }
467                $fi_dc_cats[$cat_id] = $wp_cat_id; # nécessaire pour assoc de post à post_cat ; array( dc cat iod => wp cat id )
468        }
469
470        function user($user) {
471                global $wpdb, $fi_import_format, $fi_dc_tables, $fi_dcid2wpid, $fi_update_mode;
472                extract($user);
473                if ($user_id == 'admin') {
474                        $fi_dcid2wpid[$user_id] = 1; # set dc user_id admin to wp user ID 1
475                        return; # don't modify WordPress admin
476                }
477                if ($fi_import_format == '2.0') {
478                        $user_nom = $user_name;
479                        $user_prenom = $user_firstname;
480                        $user_pseudo = $user_displayname;
481                }
482
483                $user_login = $wpdb->escape($user_id); # was $name
484                if($user_pseudo != '') { # Dotclear 1.2 : on affiche le pseudo s'il existe, sinon prénom nom
485                  $display_name = $wpdb->escape($user_pseudo);
486                } else {
487                        if($user_prenom != '') {
488                                $display_name = $wpdb->escape(trim($user_prenom.' '.$user_nom));
489                        } else {
490                                $display_name = $wpdb->escape(trim($user_nom));
491                        }
492                }
493                if($uinfo = get_userdatabylogin($user_login)) {
494                        if ($fi_update_mode) {
495                                $ret_id = wp_update_user(array(
496                                        'ID'            => $uinfo->ID,
497                                        'user_login'    => $user_login,
498                                        'user_nicename' => $display_name,
499                                        'user_email'    => $user_email,
500                                        'user_url'      => 'http://',
501                                        'display_name'  => $display_name
502                                        ));
503                                $fi_dc_tables['user']++;
504                        } else {
505                                $ret_id = $uinfo->ID;
506                                $update_meta = false;
507                        }
508                } else {
509                        $ret_id = wp_insert_user(array(
510                                'user_login'    => $user_login,
511                                'user_nicename' => $user_pseudo,
512                                'user_email'    => $user_email,
513                                'user_url'      => 'http://',
514                                'display_name'  => $display_name
515                                ));
516                        $fi_dc_tables['user']++;
517                        $update_meta = true;
518                }
519                $fi_dcid2wpid[$user_id] = $ret_id;
520               
521                if ($update_meta) {
522                        // Set Dotclear-to-WordPress permissions translation
523                        // Update Usermeta Data
524                        $user = new WP_User($ret_id);
525                        $wp_perms = $user_level + 1;
526                        if(10 == $wp_perms) { $user->set_role('administrator'); }
527                        else if(9  == $wp_perms) { $user->set_role('editor'); }
528                        else if(5  <= $wp_perms) { $user->set_role('editor'); }
529                        else if(4  <= $wp_perms) { $user->set_role('author'); }
530                        else if(3  <= $wp_perms) { $user->set_role('contributor'); }
531                        else if(2  <= $wp_perms) { $user->set_role('contributor'); }
532                        else                     { $user->set_role('subscriber'); }
533                       
534                        update_usermeta( $ret_id, 'wp_user_level', $wp_perms);
535                        update_usermeta( $ret_id, 'rich_editing', 'false');
536                        update_usermeta( $ret_id, 'first_name', $user_prenom);
537                        update_usermeta( $ret_id, 'last_name', $user_nom);
538                        update_usermeta( $ret_id, 'nickname', $user_pseudo);
539                }
540        }// End function user
541
542        function post($post) {
543                global $wpdb, $fi_dc_cats, $fi_dcposts2wpposts, $fi_import_format, $fi_dc_tables, $fi_dcid2wpid, $post_old_strings, $post_new_strings, $post_import_msg, $fi_update_mode;
544                extract($post);
545                if ($fi_import_format == '2.0') {
546                        $post_titre = $post_title;
547                        $post_content = $post_content_xhtml;
548                        $post_chapo = $post_excerpt_xhtml;
549                        $post_pub = $post_status;
550                }
551                if ( isset($post_type) ) {
552                        if($post_type != 'post') {
553                                $post_type = ($post_type == 'related') ? $post_type = 'page' : $post_type = 'post';
554                                }
555                } else {
556                        $post_type = 'post';
557                }
558                # associate post to wp user ; if dc user not found default to user ID 1 admin
559                if ( array_key_exists($user_id, $fi_dcid2wpid) ) {
560                        $post_author = $fi_dcid2wpid[$user_id];
561                } else {
562                        $post_author = 1;
563                }
564                # replace strings, example: old URL by new URL
565                $post_content = str_replace($post_old_strings, $post_new_strings, $post_content);
566
567                // Set Dotclear-to-WordPress status translation
568                $stattrans = array(0 => 'draft', 1 => 'publish');
569                $comment_status_map = array (0 => 'closed', 1 => 'open');
570               
571                $Title = $wpdb->escape($post_titre);
572                $post_content = preg_replace ('|(?<!<br />)\s*\n|', ' ', $post_content);
573                $post_excerpt = ""; # http://trac.wordpress.org/ticket/2430
574                if ($post_chapo != "") {
575                        $post_excerpt = preg_replace ('|(?<!<br />)\s*\n|', ' ', $post_chapo);
576                        $post_content = $post_excerpt ."\n<!--more-->\n".$post_content;
577                }
578                $post_excerpt = $wpdb->escape ($post_excerpt);
579                $post_content = $wpdb->escape ($post_content);
580                $post_status = $stattrans[$post_pub];
581               
582                // Import Post data into WordPress
583               
584                if($pinfo = post_exists($Title,$post_content)) {
585                        if ($fi_update_mode) {
586                                $wp_post_id = wp_update_post(array(
587                                        'ID'                            => $pinfo,
588                                        'post_author'           => $post_author,
589                                        'post_date'                     => $post_dt,
590                                        'post_date_gmt'         => $post_dt,
591                                        'post_modified'         => $post_upddt,
592                                        'post_modified_gmt'     => $post_upddt,
593                                        'post_title'            => $Title,
594                                        'post_content'          => $post_content,
595                                        'post_excerpt'          => $post_excerpt,
596                                        'post_status'           => $post_status,
597                                        'post_name'                     => $post_titre_url,
598                                        'comment_status'        => $comment_status_map[$post_open_comment],
599                                        'ping_status'           => $comment_status_map[$post_open_tb],
600                                        'post_type'                     => $post_type,
601                                        'comment_count'         => $post_nb_comment + $post_nb_trackback)
602                                        );
603                                $fi_dc_tables['post']++;
604                        } else {
605                                $wp_post_id = $pinfo;
606                        }
607                } else {
608                        $wp_post_id = wp_insert_post(array(
609                                'post_author'           => $post_author,
610                                'post_date'                     => $post_dt,
611                                'post_date_gmt'         => $post_dt,
612                                'post_modified'         => $post_modified_gmt,
613                                'post_modified_gmt'     => $post_modified_gmt,
614                                'post_title'            => $Title,
615                                'post_content'          => $post_content,
616                                'post_excerpt'          => $post_excerpt,
617                                'post_status'           => $post_status,
618                                'post_name'                     => $post_titre_url,
619                                'comment_status'        => $comment_status_map[$post_open_comment],
620                                'ping_status'           => $comment_status_map[$post_open_tb],
621                                'post_type'                     => $post_type,
622                                'comment_count'         => $post_nb_comment + $post_nb_trackback)
623                                );
624                        $fi_dc_tables['post']++;
625                }
626                $fi_dcposts2wpposts[$post_id] = $wp_post_id; # table de translation des post_id dc en ID WP
627               
628                /*_____________________________________________________________________________
629                Make Post-to-Category associations
630                assoc de post à post_cat ; array( dc cat id => wp cat id )
631                _____________________________________________________________________________*/
632                if ( array_key_exists($cat_id, $fi_dc_cats) ) { 
633                        $wp_cat_id = $fi_dc_cats[$cat_id];
634                        # Flat_Import::say($post_id.' '.$wp_post_id.' '.$wp_cat_id.' '.get_cat_name($wp_cat_id)); # 1 3 7 Tester le bouzin
635                        $cinfo = wp_set_post_categories($wp_post_id, array($wp_cat_id));
636                } else {
637                        if ($post_import_msg) {
638                                echo __('No category for post').' '.$post_id.' - '.__('associated to first category ID 1').'<br />';
639                        }
640                        $cats = get_category_to_edit(1);
641                        wp_set_post_categories($wp_post_id, $cats);
642                }
643               
644        }
645       
646        function comment($comment) {
647                global $wpdb, $fi_dcposts2wpposts, $fi_import_format, $fi_dc_tables, $fi_update_mode;
648               
649                extract($comment);
650                if ($fi_import_format == '2.0') {
651                        $comment_auteur = $comment_author;
652                        $comment_pub = $comment_status;
653                }
654                // WordPressify Data
655                $comment_ID = ltrim($comment_id, '0');
656                if ( array_key_exists($post_id, $fi_dcposts2wpposts) ) { # orphans test
657                        $comment_post_ID = $fi_dcposts2wpposts[$post_id];
658                } else {
659                        $comment_post_ID = 1; # pas de billet associé, associe à billet ID 1
660                        echo __('Orphan comment').' '.__('associated to first post ID 1').'<br />';
661                }
662                $comment_approved = "$comment_pub";
663                $name = $wpdb->escape($comment_auteur);
664                $email = $wpdb->escape($comment_email);
665                $web = "http://".$wpdb->escape($comment_site);
666                $message = $wpdb->escape( preg_replace ('|(?<!<br />)\s*\n|', ' ', $comment_content) );
667                if($cinfo = Flat_Import::wp_get_comment_ID($name, $comment_dt) ) {
668                        // Update comments
669                        if ($fi_update_mode) {
670                                $wp_comment_id = wp_update_comment(array(
671                                        'comment_ID'            => $cinfo,
672                                        'comment_post_ID'       => $comment_post_ID,
673                                        'comment_author'        => $name,
674                                        'comment_author_email'  => $email,
675                                        'comment_author_url'    => $web,
676                                        'comment_author_IP'     => $comment_ip,
677                                        'comment_date'          => $comment_dt,
678                                        'comment_date_gmt'      => $comment_dt,
679                                        'comment_content'       => $message,
680                                        'comment_approved'      => $comment_approved)
681                                        );
682                                $fi_dc_tables['comment']++;
683                        } else {
684                                $wp_comment_id = $cinfo;
685                        }
686                } else {
687                        // Insert comments
688                        $wp_comment_id = wp_insert_comment(array(
689                                'comment_post_ID'       => $comment_post_ID,
690                                'comment_author'        => $name,
691                                'comment_author_email'  => $email,
692                                'comment_author_url'    => $web,
693                                'comment_author_IP'     => $comment_ip,
694                                'comment_date'          => $comment_dt,
695                                'comment_date_gmt'      => $comment_dt,
696                                'comment_content'       => $message,
697                                'comment_approved'      => $comment_approved)
698                                );
699                        $fi_dc_tables['comment']++;
700                }
701        } # comment
702       
703        function link($link) {
704        /*
705        la position détermine la catégorie de liens d'appartenance ; sauf si toutes les positions sont à zéro, c'est alors le link_id qui détermine la position
706        ceci empêche l'assoc de lien à link_category ici ; on doit le faire en post-proc
707        au départ on associe le lien à la catégorie cat_id 1 Blogroll pour les liens dc sans catégorie
708         associate links to cat based on dc position or link_id if all dc positions at zero
709         $fi_linkcat_pos associe au cat_id ds => wp_categories la position dc
710         $fi_linkcat_link_id associe au cat_id ds wp_categories => le link_id dc
711         $fi_link_pos associe au link_id ds wp_links => la position dc
712         $fi_link_link_id associe au link_id ds wp_links => le link_id dc
713        */
714                global $wpdb, $fi_linkcat_pos, $fi_linkcat_link_id, $fi_link_pos, $fi_link_link_id, $fi_import_format, $fi_dc_tables, $fi_update_mode;
715                extract($link);
716                if ($fi_import_format == '2.0') {
717                        $href = $link_href;
718                        $label = $link_title;
719                        $title = $link_desc;
720                        $lang = $link_lang;
721                        $rel = $link_xfn;
722                        $position = $link_position;
723                }
724                $title = addslashes($title);
725                if ( ($href == "") AND ($title != "") ) { # on traite une catégorie de lien
726                        if ( !($wp_link_category_id = Flat_Import::link_category_exists($title) ) ) {
727                                $wp_link_category_id = Flat_Import::wp_create_link_category($title);
728                        }
729                        $fi_linkcat_pos[$wp_link_category_id] = $position;
730                        $fi_linkcat_link_id[$wp_link_category_id] = $link_id;
731                } else { # on traite un lien
732                        $linkname = $wpdb->escape($label);
733                        $description = $wpdb->escape($title);
734                        $wp_link_id = Flat_Import::link_exists($linkname, $href, $description);
735                        if($wp_link_id) {
736                                if ($fi_update_mode) {
737                                        $ret_id = wp_update_link( array(
738                                                'link_id'               => $wp_link_id,
739                                                'link_url'              => $href,
740                                                'link_name'             => $linkname,
741                                                'link_description'      => $description
742                                                )
743                                                );
744                                        $fi_dc_tables['link']++;
745                                } else {
746                                        $ret_id = $wp_link_id;
747                                }
748                        } else {
749                                $ret_id = wp_insert_link( array(
750                                        'link_url'              => $href,
751                                        'link_name'             => $linkname,
752                                        'link_description'      => $description
753                                        )
754                                        );
755                                $fi_dc_tables['link']++;
756                        }
757                        $fi_link_pos[$ret_id] = $position;
758                        $fi_link_link_id[$ret_id] = $link_id;
759                }
760        }
761
762        function post_meta($tags) {
763                Flat_Import::meta($tags, 'post_meta');
764        }
765        function meta($tags, $fi_table_name='meta') 
766        {
767                global $wpdb, $utw, $STagging, $STaggingAdmin, $fi_import_format, $fi_dc_tables, $fi_dcposts2wpposts;
768                extract($tags);
769                $tag = '';
770                if ($fi_import_format == '1.2') {
771                        if ($meta_key == 'tag') $tag = $meta_value;
772                } elseif ($fi_import_format == '2.0') {
773                        if ($meta_type == 'tag') $tag = $meta_id;
774                }
775                if ($tag != '') {
776                        if ( array_key_exists($post_id, $fi_dcposts2wpposts) ) {
777                                $post_id = $fi_dcposts2wpposts[$post_id]; # get WP post_id
778                                wp_add_post_tags($post_id, $tag);
779                                $fi_dc_tables[$fi_table_name]++;
780                        }
781                }
782        }
783        /*_____________________________________________________________________________
784                some WP functions not found in WP 2.3
785        _____________________________________________________________________________*/
786        function wp_nonce_meta_refresh($action = -1, $url = 'admin.php', $name = "_wpnonce", $referer = true) {
787                # do a meta refresh ; the original one was: echo '<meta http-equiv="refresh" content="0">'; to refresh the current page
788                $name = attribute_escape($name);
789                $ret = '<meta http-equiv="refresh" content="0;'.$url.'&'.$name.'='.wp_create_nonce($action).'">';
790                if ( $referer )
791                        wp_referer_field();
792                return $ret;
793        }
794       
795        function wp_get_comment_ID($name, $comment_dt) {
796                global $wpdb;
797                return $wpdb->get_var("SELECT comment_ID FROM $wpdb->comments WHERE comment_author = '$name' AND comment_date = '$comment_dt'");
798        }
799
800        function link_exists($link_name, $link_url, $link_description) {
801                global $wpdb;
802                return $wpdb->get_var("SELECT link_id FROM $wpdb->links WHERE link_name = '$link_name' AND link_url = '$link_url' AND link_description = '$link_description'");
803        }
804       
805        function link_category_exists($link_cat_name) {
806                $id = is_term($link_cat_name, 'link_category');
807                if ( is_array($id) )
808                        $id = $id['term_id'];
809                return $id;
810        }
811       
812        function wp_create_link_category($link_cat_name) {
813        /*
814        if ( $id = Flat_Import::link_category_exists($link_cat_name) )
815                return $id;
816        */
817        $id = wp_insert_term($link_cat_name, 'link_category');
818        if ( is_array($id) )
819                $id = $id['term_id'];
820        return $id;
821        }
822        /*_____________________________________________________________________________
823                miscellaneous functions
824        _____________________________________________________________________________*/
825        function filesize_format($bytes) {
826                $bytes=(float)$bytes;
827                if ($bytes<1024){
828                $numero=number_format($bytes, 0, ',', '.')." Byte";
829                return $numero;
830                }
831                if ($bytes<1048576){
832                 $numero=number_format($bytes/1024, 2, ',', '.')." KByte";
833                return $numero;
834                }
835                if ($bytes>=1048576){
836                 $numero=number_format($bytes/1048576, 2, ',', '.')." MByte";
837                return $numero;
838                }
839        }
840
841        function say($str) { # add html tags and force output
842                echo $str.'<br />';
843                ob_flush();flush();
844        }
845        /*_____________________________________________________________________________
846                Admin display
847        _____________________________________________________________________________*/
848        function tips() {
849                echo '<p>'.__('Welcome to WordPress.  We hope (and expect!) that you will find this platform incredibly rewarding!  As a new WordPress user coming from Dotclear, there are some things that we would like to point out.  Hopefully, they will help your transition go as smoothly as possible.').'</p>';
850                echo '<h3>'.__('Users').'</h3>';
851                echo '<p>'.sprintf(__('You have already setup WordPress and have been assigned an administrative login and password.  This one (admin) is preserved.  We have taken care to import all of your users into our system (except the admin one).  It is safe to change your passwords.  So <a href="%1$s">Login</a> and change them.'), '../wp-login.php').'</p>';
852                echo '<h3>'.__('Preserving Authors').'</h3>';
853                echo '<p>'.__('We have attempted to preserve post authors.  If you are the only author or contributor to your blog, then you are safe.  In most cases, we are successful in this preservation endeavor.  However, if we cannot ascertain the name of the writer due to discrepancies between database tables, we assign it to you, the administrative user.').'</p>';
854                echo '<h3>'.__('WordPress Resources').'</h3>';
855                echo '<p>'.__('Finally, there are numerous WordPress resources around the internet.  Some of them are:').'</p>';
856                echo '<ul>';
857                echo '<li>'.__('<a href="http://www.wordpress.org">The official WordPress site</a>').'</li>';
858                echo '<li>'.__('<a href="http://wordpress.org/support/">The WordPress support forums</a>').'</li>';
859                echo '<li>'.__('<a href="http://codex.wordpress.org">The Codex (In other words, the WordPress Bible)</a>').'</li>';
860                echo '</ul>';
861                echo '<p>'.sprintf(__('That\'s it! What are you waiting for? Go <a href="%1$s">login</a>!'), '../wp-login.php').'</p>';
862        }
863
864        function header() {
865                echo '<div class="wrap">';
866                echo '<h2>'.__('Import Dotclear').'</h2>';
867        }
868
869        function footer() {
870                echo '</div>';
871        }
872       
873        function greet() {
874                $filename = dirname(__FILE__).'/../../wp-content/uploads/blog-backup.txt';
875                $filename_exists = ( file_exists($filename) ) ? true : false;
876                $recover_filename = dirname(__FILE__).'/../../wp-content/uploads/blog-backup-recovery.txt';
877                $recover_exists = ( file_exists($recover_filename) ) ? true : false;
878                if ($recover_exists) {
879                        if ( filesize($recover_filename) == 0) $recover_exists = false;
880                }
881                echo '<p>'.__('This importer allows you to import a Dotclear blog into a WordPress blog.').'</p>';
882                echo '<p>'.__('Import of posts (users, comments, categories, tags), links (categories), from DotClear 2 or Dotclear 1.2.x.').'</p>';
883                echo '<p>'.__('It requires the <em>wp-contents/uploads/</em><strong>blog-backup.txt</strong> file.').'</p>';
884                echo '<p>'.__('The first post <strong>ID 1</strong> ; <em>Hello World</em> initial name (for orphans comments) is required.').'</p>';
885                echo '<p>'.__('If the importer do not display the message:').' <strong>'.__('End of import').'</strong>, '.
886                __('then <strong>retry</strong> the import. Click <em>Import</em>, click <em>Dotclear flat import</em> and so on.').'</p>';
887                echo '<p>'.__('<strong>Saving</strong> your existing WordPress data is <strong>mandatory</strong> before doing an import. The version 2 of <a href="http://www.ilfilosofo.com/blog/wp-db-backup">WordPress Database Backup</a> is recommended for WordPress 2.1+.').'</p>';
888                if ( (WPLANG == 'fr_FR') AND ( file_exists('import/flatimport-tuto-fr.html')) ) {
889                        echo '<strong>Tutoriel:</strong> <a href="import/flatimport-tuto-fr.html">Comment importer un blog de Dotclear vers WordPress 2.3+</a>.';
890                } elseif ( file_exists('import/flatimport-tuto.html') ) {
891                        echo '<strong>Tutorial:</strong> <a href="import/flatimport-tuto.html">How to import a blog from Dotclear to WordPress 2.3+</a>';
892                }
893                echo '<p><strong>'.__('Forum:').'</strong> <a href="http://www.wordpress-fr.net/support/sujet-2944-import-dotclear-fichier-texte">[Import] Dotclear par fichier texte</a>.</p>';
894                if ($filename_exists AND $recover_exists) {
895                        echo '<form action="admin.php?import=flatimport&amp;step=3" method="post">';
896                        wp_nonce_field('import-flatimport');
897                        echo '<input type="submit" name="submit" value="'.attribute_escape(__('Continue')).'" />';
898                        echo ' '.__('the import from the latest point of control (if not wanted, please delete the wp-contents/uploads/<strong>blog-backup-recovery.txt</strong> file ; then retry the import').'.';
899                        echo '</form>';
900                } elseif ($filename_exists) {
901                        echo '<form action="admin.php?import=flatimport&amp;step=1" method="post">';
902                        wp_nonce_field('import-flatimport');
903                        echo '<input type="submit" name="submit" value="'.attribute_escape(__('Import')).'" />';
904                        echo ' '.__('Import posts (users, comments, tags, categories), links (categories). <em>New ones only</em>.');
905                        echo '</form>';
906                        echo '<form action="admin.php?import=flatimport&amp;step=2" method="post">';
907                        wp_nonce_field('import-flatimport');
908                        echo '<input type="submit" name="submit" value="'.attribute_escape(__('Update')).'" />';
909                        echo ' '.__('Update posts (users, comments, tags, categories), links (categories). <em>Import new ones, update already imported ones</em>.');
910                        echo '</form>';
911                } else {
912                        echo '<p><strong>Warning:</strong> No wp-contents/uploads/<strong>blog-backup.txt</strong> file found.</p>';
913                }
914        }
915        /*_____________________________________________________________________________
916                main dispatching
917        _____________________________________________________________________________*/
918        function dispatch() {
919                global $fi_update_mode;
920
921                $step = ( empty($_GET['step']) ) ? 0 : ( (int) $_GET['step'] ); # securize numeric $_GET
922               
923                $this->header();
924
925                if ( $step > 0 ) {
926                        check_admin_referer('import-flatimport');
927                }
928               
929                switch ($step) {
930                        default:
931                        case 0 :
932                                $this->greet(); # Home
933                                break;
934                        case 1 :
935                                $fi_update_mode = false; # Import
936                                $this->import_flat_file();
937                                break;
938                        case 2 :
939                                $fi_update_mode = true; # Update
940                                $this->import_flat_file();
941                                break;
942                        case 3 :
943                                $fi_update_authorized = false; # Continue with the default for a non valid blog-backup-recovery.txt
944                                $this->import_flat_file();
945                                break;
946                        case 4 :
947                                $this->tips(); # Tips
948                                break;
949                }
950                $this->footer();
951        }
952       
953        function Flat_Import() {
954                // Nothing.     
955        }
956}
957/*_____________________________________________________________________________
958        define import object and execute
959_____________________________________________________________________________*/
960$fi_dc_import = new Flat_Import();
961register_importer('flatimport', __('Dotclear flat import'), __('Import <strong>posts</strong><em>(users, comments, tags, categories)</em>, <strong>pages</strong><em>(as posts)</em>, <strong>links</strong><em>(categories)</em> from a Dotclear 2 or 1 export file'), array ($fi_dc_import, 'dispatch'));
962?>