/[drupal]/contributions/modules/phorum/phorum_converter.module
ViewVC logotype

Contents of /contributions/modules/phorum/phorum_converter.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Tue Apr 29 20:56:18 2008 UTC (18 months, 4 weeks ago) by greggles
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-5
Changes since 1.1: +26 -19 lines
File MIME type: text/x-php
task #157310 by rkeppner: update phorum converter to drupal 5 API
1 <?php
2
3 // $Id: phorum_converter.module,v 1.1 2007/01/23 17:59:54 greggles Exp $
4
5 /**
6 * @file
7 * Converts Phorum database data into drupal's own forum
8 * Converts:
9 * user basic data
10 * containers (or folders in phorum terminology) and forums, puts them into hierarchy
11 */
12
13 /*
14 NOTE: disabling forums, containers? global topics?
15 */
16
17 /**
18 * Implementation of hook_help().
19 */
20 function phorum_converter_help($section) {
21 switch ($section) {
22 case 'admin/help#phorum_converter':
23 $output = '<p>'. t("Converts Phorum DB data into drupal's forum") .'</p>';
24 return $output;
25 case 'admin/modules#description':
26 return t("Converts Phorum DB data into Drupal's forum. Please do not forget to enable forum module as well and to visit this module's settings page as well.");
27 }
28 }
29
30 /**
31 * Implementation of hook_menu().
32 */
33 function phorum_converter_menu($may_cache) {
34 $items = array();
35
36 if ($may_cache) {
37 $items[] = array(
38 'path' => 'admin/settings/phorum',
39 'title' => t('Phorum conversion'),
40 'description' => t('Configure the phorum conversion module.'),
41 'callback' => 'drupal_get_form',
42 'callback arguments' => array('phorum_converter_admin_form'),
43 'access' => user_access('administer forums'),
44 'type' => MENU_NORMAL_ITEM,
45 );
46 $items[] = array('path' => 'phorum',
47 'title' => t('Phorum conversion'),
48 'callback' => 'phorum_converter_cron',
49 'access' => user_access('administer forums'),
50 'type' => MENU_NORMAL_ITEM,
51 );
52 }
53
54 return $items;
55 }
56
57 function phorum_converter_admin_form() {
58 $form = array();
59 $form['phorum_converter_prefix'] = array(
60 '#type' => 'textfield',
61 '#title' => t("Phorum table's prefix"),
62 '#default_value' => variable_get('phorum_converter_prefix', 'phorum'),
63 );
64 $form['phorum_converter_runtime'] = array(
65 '#type' => 'textfield',
66 '#title' => t('Cron-script runtime (minutes)'),
67 '#description' => t('The amount of time being allowed for the converter-cron to run in minutes'),
68 '#default_value' => variable_get('phorum_converter_runtime', '2'),
69 );
70 $roles = array();
71 $result = db_query('SELECT rid, name FROM {role}');
72 while ($role = db_fetch_object($result)) {
73 $roles[$role->rid] = $role->name;
74 }
75 $form['phorum_converter_admin_role'] = array(
76 '#type' => 'select',
77 '#title' => t('Role for forum admins'),
78 '#description' => t('This role will be given for the users specified admins by the Phorum data'),
79 '#default_value' => variable_get('phorum_converter_admin_role', 0),
80 '#options' => $roles,
81 );
82 $filters = array();
83 $rs = db_query("SELECT * FROM {filter_formats} WHERE roles LIKE '%%,%d,%%'", DRUPAL_AUTHENTICATED_RID);
84 while ($row = db_fetch_object($rs)) {
85 $filters[$row->format] = $row->name;
86 }
87 $form['phorum_converter_msg_format'] = array(
88 '#type' => 'select',
89 '#title' => t('Please specify the message filtering'),
90 '#description' => t('This filter will be applied to the converted messages. Only those filters are listed here which are available for the authenticated users'),
91 '#default_value' => variable_get('phorum_converter_msg_format', 1),
92 '#options' => $filters,
93 );
94 return system_settings_form($form);
95 }
96
97 function phorum_converter_cron() {
98 ini_set('max_execution_time', 0);
99 // check if the settings are right
100 if (!function_exists("_forum_get_vid")) {
101 watchdog('phorum converter', t('The converter needs the forum module to be enabled.'));
102 return;
103 }
104 if (variable_get('phorum_converter_admin_role', 0) == 0) {
105 watchdog('phorum converter', t('Please visit the settings page to set the required parameters for the conversion'));
106 return;
107 }
108 $prefix = variable_get('phorum_converter_prefix', 'phorum');
109 $table = empty($prefix) ? 'forums' : $prefix .'_forums';
110 db_set_active('phorum');
111 $rs = db_query_range("SELECT forum_id FROM $table", 0, 1);
112 if (db_num_rows($rs) == 0) {
113 watchdog('phorum converter', t('Phorum DB can not be found. Please check if the Phorum DB access information is right in the settings.php file or if the prefix field is set correctly on the admin/settings/phorum_converter page.'));
114 db_set_active();
115 return;
116 }
117 db_set_active();
118 $phase = variable_get('phorum_converter_phase', 'users');
119 $runtime = variable_get('phorum_converter_runtime', '2');
120 $end_time = time() + 60*$runtime;
121 while ($end_time > time()) {
122 $start_id = variable_get('phorum_converter_phase_arg', 0);
123 switch ($phase) {
124 case 'init':
125 _phorum_converter_init($start_id, $end_time);
126 break;
127 case 'users':
128 _phorum_converter_users($start_id, $end_time);
129 break;
130 case 'cf':
131 // this step handles the containers and forums, except the hierarchy
132 // _forum_get_vid is the forum module's own function, it will create the
133 // necessery vocabulary data if not yet exists
134 $forum_vid = _forum_get_vid();
135 _phorum_converter_cf($start_id, $end_time, $forum_vid);
136 break;
137 case 'cf_hierarchy':
138 _phorum_converter_cf_hierarchy($start_id, $end_time);
139 break;
140 case 'messages':
141 _phorum_converter_messages($start_id, $end_time);
142 break;
143 case 'read_flags':
144 _phorum_converter_message_read_flags($start_id, $end_time);
145 break;
146 }
147 if ($end_time > time()) {
148 if ($phase == 'finish') {
149 watchdog('phorum converter', t('The Phorum converter has finished its work.'));
150 break;
151 }
152 $phase = _phorum_converter_get_next_phase($phase);
153 variable_set('phorum_converter_phase', $phase);
154 variable_set('phorum_converter_phase_arg', 0);
155 }
156 }
157 return;
158 }
159
160 /**
161 * Determines the next phase in the conversion road
162 *
163 * @param $phase the actual phase
164 * @return the next phase
165 */
166 function _phorum_converter_get_next_phase($phase) {
167 $phases = array('users', 'cf', 'cf_hierarchy', 'messages', 'read_flags', 'finish');
168 $current_found = FALSE;
169 $next_phase = '';
170 foreach ($phases as $actual) {
171 if ($current_found) {
172 $next_phase = $actual;
173 break;
174 }
175 if ($phase == $actual) {
176 $current_found = TRUE;
177 }
178 }
179 return $next_phase;
180 }
181
182 /**
183 * Takes the user's from the phorum DB and inserts it into drupal
184 */
185 function _phorum_converter_users($start_id, $end_time) {
186 $prefix = variable_get('phorum_converter_prefix', 'phorum');
187 $table = empty($prefix) ? 'users' : $prefix .'_users';
188 db_set_active('phorum');
189 $rs = db_query("SELECT * FROM $table WHERE user_id > %d ORDER BY user_id ASC", $start_id);
190 while (($row = db_fetch_object($rs)) && ($end_time > time())) {
191 db_set_active();
192 $uid = db_result(db_query("SELECT uid FROM {users} WHERE name = '%s'", $row->username));
193 if (!$uid) {
194 // get an available username - commented out since users should have been imported already
195 // $row->username = _phorum_converter_get_username($row->username);
196 // user_save cannot be used straightforward since that would MD5 hash the
197 // already hashed password
198 $uid = db_next_id('{users}_uid');
199 db_query("INSERT INTO {users} (uid, name, pass, mail, status, signature, created, timezone)
200 VALUES(%d, '%s', '%s', '%s', %d, '%s', %d, '%s')",
201 $uid, $row->username, $row->password, $row->email, $row->active, $row->signature, $row->date_added, (3600*$row->tz_offset));
202 }
203 db_query("INSERT INTO {phorum_tmp_user_join} (phorum, drupal) VALUES(%d, %d)", $row->user_id, $uid);
204 db_query("INSERT INTO {phorum_users} (uid, email_notify, post_count) VALUES(%d, %d, %d)", $uid, $row->email_notify, $row->posts);
205 $role_exists = db_result(db_query("SELECT uid FROM {users_roles} WHERE uid = %d AND rid = %d", $uid, variable_get('phorum_converter_admin_role', 0)));
206 if ($row->admin && empty($role_exists)) {
207 db_query("INSERT INTO {users_roles} (uid, rid) VALUES(%d, %d)", $uid, variable_get('phorum_converter_admin_role', 0));
208 }
209 variable_set('phorum_converter_phase_arg', $uid);
210 db_set_active('phorum');
211 }
212 db_set_active();
213 }
214
215 /**
216 * This function checks for a string if that username has been already taken or not.
217 * In case it is already used it will give an other non taken.
218 *
219 * @param $name the username to be checked
220 * @return not yet used username
221 */
222 function _phorum_converter_get_username($name) {
223 $postfix = "";
224 do {
225 $testing = $name . $postfix;
226 $rs = db_query("SELECT uid FROM {users} WHERE name = '%s'", $testing);
227 $postfix = "_". rand(100, 999);
228 } while (db_num_rows($rs) > 0);
229 return $testing;
230 }
231
232 /**
233 * Takes the containers (or folders in phorum terminology) and forums and
234 * inserts it into drupal. Hierarchy settings is only in the next step
235 */
236 function _phorum_converter_cf($start_id, $end_time, $forum_vid) {
237 $prefix = variable_get('phorum_converter_prefix', 'phorum');
238 $table = empty($prefix) ? 'forums' : $prefix .'_forums';
239 db_set_active('phorum');
240 $rs = db_query("SELECT name, description, display_order AS weight, folder_flag, forum_id FROM $table WHERE forum_id > %d ORDER BY forum_id ASC", $start_id);
241 while (($term = db_fetch_array($rs)) && ($end_time > time())) {
242 db_set_active();
243 $term['vid'] = $forum_vid;
244 taxonomy_save_term($term);
245 if ($term['folder_flag'] == 1) {
246 $containers = variable_get('forum_containers', array());
247 $containers[] = $term['tid'];
248 variable_set('forum_containers', $containers);
249 }
250 db_query("INSERT INTO {phorum_tmp_forum_join} (phorum, drupal) VALUES(%d, %d)", $term['forum_id'], $term['tid']);
251 variable_set('phorum_converter_phase_arg', $term['forum_id']);
252 db_set_active('phorum');
253 }
254 db_set_active();
255 }
256
257 /**
258 * Takes the containers (or folders in phorum terminology) and forums and
259 * puts them into the hierarchy tree
260 */
261 function _phorum_converter_cf_hierarchy($start_id, $end_time) {
262 $prefix = variable_get('phorum_converter_prefix', 'phorum');
263 $table = empty($prefix) ? 'forums' : $prefix .'_forums';
264 db_set_active('phorum');
265 $rs = db_query("SELECT forum_id, parent_id FROM $table WHERE forum_id > %d AND parent_id > 0 ORDER BY forum_id ASC", $start_id);
266 while (($row = db_fetch_object($rs)) && ($end_time > time())) {
267 db_set_active();
268 $tid = db_result(db_query("SELECT drupal FROM {phorum_tmp_forum_join} WHERE phorum = %d", $row->forum_id));
269 $ptid = db_result(db_query("SELECT drupal FROM {phorum_tmp_forum_join} WHERE phorum = %d", $row->parent_id));
270 $term = (array)taxonomy_get_term($tid);
271 $term['parent'] = $ptid;
272 taxonomy_save_term($term);
273 variable_set('phorum_converter_phase_arg', $row->forum_id);
274 db_set_active('phorum');
275 }
276 db_set_active();
277 }
278
279 /**
280 * Takes the messages and converts them into drupal structure.
281 */
282 function _phorum_converter_messages($start_id, $end_time) {
283 $prefix = variable_get('phorum_converter_prefix', 'phorum');
284 $table = empty($prefix) ? 'messages' : $prefix .'_messages';
285 db_set_active('phorum');
286 $rs = db_query("SELECT * FROM $table WHERE message_id > %d ORDER BY message_id ASC", $start_id);
287 while (($row = db_fetch_object($rs)) && ($end_time > time())) {
288 $row->body = str_replace("px]", "]", $row->body);
289 db_set_active();
290 $uid = db_result(db_query("SELECT drupal FROM {phorum_tmp_user_join} WHERE phorum = %d", $row->user_id));
291 $cid = 0;
292 // can not use node_save since that would overwrite the created and modify timestamps
293 if ($row->parent_id == 0) {
294 $tid = db_result(db_query("SELECT drupal FROM {phorum_tmp_forum_join} WHERE phorum = %d", $row->forum_id));
295 if ($row->message_id != $row->thread) {
296 // we have a moved topic's left-behind entry at hand
297 // Phorum: when moving a topic they have rewritten the forum_id then
298 // made a new message pointing to this older one. Thread is the id of the
299 // topic starter message
300 $nid = db_result(db_query("SELECT nid FROM {phorum_tmp_message_join} WHERE phorum = %d", $row->thread));
301 db_query("INSERT INTO {term_node} (nid, tid) VALUES(%d, %d)", $nid, $tid);
302 }
303 else {
304 // we have a topic at hand
305 $nid = db_next_id('{node}_nid');
306 $vid = db_next_id('{node_revisions}_vid');
307 db_query("INSERT INTO {forum} (nid, vid, tid) VALUES(%d, %d, %d)", $nid, $vid, $tid);
308 db_query("INSERT INTO {term_node} (nid, tid) VALUES(%d, %d)", $nid, $tid);
309 // for the changed filed we can not use the Phorum's modifydate Phorum sets that for the last message's timestamp in the said thread
310 db_query("INSERT INTO {node}
311 (nid, vid, type, title, uid, status, created, changed, comment, promote, moderate, sticky)
312 VALUES(%d, %d, '%s', '%s', %d, %d, %d, %d, %d, %d, %d, %d)",
313 $nid, $vid, 'forum', $row->subject, $uid, ($row->status == 2), $row->datestamp,
314 $row->datestamp, ($row->closed == 0 ? 2 : 1), 0, ($row->status == -1), ($row->sort == 1));
315 db_query("INSERT INTO {node_revisions}
316 (nid, vid, uid, title, body, teaser, log, timestamp, format)
317 VALUES(%d, %d, %d, '%s', '%s', '%s', '%s', %d, %d)", $nid, $vid, $uid, $row->subject,
318 $row->body, $row->body, '', $row->datestamp, variable_get('phorum_converter_msg_format', 1));
319 db_query("INSERT INTO {node_comment_statistics}
320 (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count)
321 VALUES(%d, %d, '%s', %d, %d)", $nid, $row->datestamp, NULL, $uid, 0);
322 }
323 }
324 else {
325 // we have a reply at hand
326 $row2 = db_fetch_object(db_query("SELECT drupal, nid FROM {phorum_tmp_message_join} WHERE phorum = %d", $row->parent_id));
327 // comment parent id
328 $pid = $row2->drupal;
329 $nid = $row2->nid;
330 $cid = db_next_id('{comments}_cid');
331 $thread = _phorum_convert_determine_thread($pid, $nid);
332 // Phorum's modifystamp is only set at the topic starter messages, therefore it will be 0 here, so the timestamp will be the createdate
333 db_query("INSERT INTO {comments}
334 (cid, pid, nid, uid, subject, comment, hostname, timestamp, score, status, format, thread)
335 VALUES(%d, %d, %d, %d, '%s', '%s', '%s', %d, %d, %d, %d, '%s')",
336 $cid, $pid, $nid, $uid, $row->subject, $row->body, $row->ip, $row->datestamp, 0,
337 (($row->status == 2) ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED), variable_get('phorum_converter_msg_format', 1), $thread);
338 db_query("UPDATE {node_comment_statistics}
339 SET last_comment_timestamp = %d, last_comment_uid = %d, comment_count = comment_count +1
340 WHERE nid = %d", $row->datestamp, $uid, $nid);
341 }
342 // since moved topics do not get node's and such there is no need to scribe them up on the following table
343 // moved: thread != message_id && parent_id == 0 => insert when parent_id != 0 || (parent_id == 0 && message_id != thread)
344 // which is equavilent with:
345 if ($row->parent_id != 0 || $row->message_id == $row->thread) {
346 db_query("INSERT INTO {phorum_tmp_message_join} (phorum, drupal, nid) VALUES(%d, %d, %d)", $row->message_id, $cid, $nid);
347 }
348 variable_set('phorum_converter_phase_arg', $row->message_id);
349 db_set_active('phorum');
350 }
351 db_set_active();
352 }
353
354 /**
355 * Sets the read states for the forums / topics
356 * Phorum: user_id - forum_id - message_id (user_newflags)
357 * Drupal: uid - nid - timestamp (history) where nid is the topic's node's id
358 *
359 * uid - comes from user_id pretty obvious
360 * nid - can derive from the phorum_tmp_message_join
361 * timestamp - using the messaged_id get the created field from either node or comments table
362 *
363 * Development: message_id is not unique this time, so if the cron breaks on
364 * the next run it can take some rows that has been already processed. In a
365 * very extrame case it might not even proceed to non processed rows ***
366 */
367 function _phorum_converter_message_read_flags($start_id, $end_time) {
368 $prefix = variable_get('phorum_converter_prefix', 'phorum');
369 $table = empty($prefix) ? 'user_newflags' : $prefix .'_user_newflags';
370 db_set_active('phorum');
371 $rs = db_query("SELECT * FROM $table WHERE user_id > 0 AND message_id > %d ORDER BY message_id ASC", $start_id);
372 while (($row = db_fetch_object($rs)) && ($end_time > time())) {
373 db_set_active();
374 $uid = db_result(db_query("SELECT drupal FROM {phorum_tmp_user_join} WHERE phorum = %d", $row->user_id));
375 $msg = db_fetch_object(db_query("SELECT drupal as cid, nid FROM {phorum_tmp_message_join} WHERE phorum = %d", $row->message_id));
376 if (empty($msg->cid)) {
377 $msg->timestamp = db_result(db_query("SELECT timestamp FROM {comments} WHERE cid = %d", $msg->cid));
378 }
379 else {
380 $msg->timestamp = db_result(db_query("SELECT created FROM {node} WHERE nid = %d", $msg->nid));
381 }
382 $timestamp = db_result(db_query("SELECT timestamp FROM {history} WHERE uid = %d AND nid = %d", $uid, $msg->nid));
383 if (empty($timestamp)) {
384 db_query("REPLACE INTO {history} (uid, nid, timestamp) VALUES(%d, %d, %d)", $uid, $msg->nid, $msg->timestamp);
385 }
386 elseif ($timestamp < $msg->timestamp) {
387 db_query("UPDATE {history} SET timestamp = %d WHERE uid = %d AND nid = %d", $msg->timestamp, $uid, $msg->nid);
388 }
389 if ($start_id != $row->message_id) {
390 variable_set('phorum_converter_phase_arg', $row->message_id);
391 }
392 db_set_active('phorum');
393 }
394 db_set_active();
395 }
396
397 /**
398 * comment.module code to determine the thread field
399 */
400 function _phorum_convert_determine_thread($pid, $nid) {
401 $thread = '';
402 if ($pid == 0) {
403 // This is a comment with no parent comment (depth 0): we start
404 // by retrieving the maximum thread level.
405 $max = db_result(db_query('SELECT MAX(thread) FROM {comments} WHERE nid = %d', $nid));
406
407 // Strip the "/" from the end of the thread.
408 $max = rtrim($max, '/');
409
410 // Finally, build the thread field for this new comment.
411 $thread = int2vancode(vancode2int($max) + 1) .'/';
412 }
413 else {
414 // This is comment with a parent comment: we increase
415 // the part of the thread value at the proper depth.
416
417 // Get the parent comment:
418 $parent = _comment_load($pid);
419
420 // Strip the "/" from the end of the parent thread.
421 $parent->thread = (string) rtrim((string) $parent->thread, '/');
422
423 // Get the max value in _this_ thread.
424 $max = db_result(db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE '%s.%%' AND nid = %d", $parent->thread, $nid));
425
426 if ($max == '') {
427 // First child of this parent.
428 $thread = $parent->thread .'.'. int2vancode(0) .'/';
429 }
430 else {
431 // Strip the "/" at the end of the thread.
432 $max = rtrim($max, '/');
433
434 // We need to get the value at the correct depth.
435 $parts = explode('.', $max);
436 $parent_depth = count(explode('.', $parent->thread));
437 $last = $parts[$parent_depth];
438
439 // Finally, build the thread field for this new comment.
440 $thread = $parent->thread .'.'. int2vancode(vancode2int($last) + 1) .'/';
441 }
442 }
443 return $thread;
444 }

  ViewVC Help
Powered by ViewVC 1.1.2