/[drupal]/contributions/modules/og2list/og2list.module
ViewVC logotype

Contents of /contributions/modules/og2list/og2list.module

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


Revision 1.109 - (show annotations) (download) (as text)
Sun Aug 5 12:35:31 2007 UTC (2 years, 3 months ago) by killes
Branch: MAIN
CVS Tags: HEAD
Changes since 1.108: +10 -1 lines
File MIME type: text/x-php
#152161, Cannot add mailing list recipient to group node once it has already been created, patch by damien_vancouver
1 <?php
2 // $Id: og2list.module,v 1.108 2007/08/05 12:30:19 killes Exp $
3
4 // Defines for outgoing mail
5 define('OG2LIST_OUTGOING_NOT_SENT', 1);
6 define('OG2LIST_OUTGOING_RECEIVED_BY_MTA', 2);
7 define('OG2LIST_OUTGOING_LOCAL_ERROR', 3);
8 define('OG2LIST_OUTGOING_REMOTE_ERROR',4);
9 define('OG2LIST_OUTGOING_POSTPONED', 5);
10 define('OG2LIST_OUTGOING_MODERATED', 6);
11 define('OG2LIST_OUTGOING_DIGEST', 7);
12
13 /**
14 * Implementation of hook_help.
15 */
16 function og2list_help($section) {
17 $output = '';
18 switch($section) {
19 case 'admin/help#og2list':
20 case 'admin/modules#description':
21 $output = t('Connect your mailing lists to your drupal site and your drupal site to your mailing lists. Needs OG.module, OG_forum.module, forum.module, and taxonomy.module.');
22 break;
23 }
24 return $output;
25 }
26
27 /**
28 * Implementation of hook_perm.
29 *
30 * 'administer og2list': not currently used
31 * 'subscribe to lists by mail': checkes if a role may subscribe by mail
32 */
33 function og2list_perm() {
34 return array('administer og2list', 'subscribe to lists');
35 }
36
37 /**
38 * Implementation of hook_menu.
39 */
40 function og2list_menu($may_cache) {
41
42 $items = array();
43
44 if ($may_cache) {
45 $access = user_access('post comments');
46 $items[] = array('path' => 'comment/edit',
47 'title' => t('edit comment'),
48 'callback' => 'og2list_comment_edit',
49 'access' => $access,
50 'type' => MENU_CALLBACK);
51
52 $items[] = array(
53 'path' => 'admin/og/og2list',
54 'title' => t('Organic Groups List Manager'),
55 'description' => t('Configure Og2List settings'),
56 'callback' => 'drupal_get_form',
57 'callback arguments' => 'og2list_admin_settings',
58 'access' => user_access('administer site configuration'),
59 'type' => MENU_NORMAL_ITEM, // optional
60 );
61 }
62 else {
63 if (arg(0) == 'node' && is_numeric(arg(1))) {
64 $node = node_load(arg(1));
65 if (og_is_group_type($node->type) && isset($node->og2list_ml)) {
66 $items[] = array('path' => 'node/'. arg(1). '/listmail',
67 'title' => t('Mailing list'),
68 'callback' => 'og2list_listmail',
69 'callback arguments' => array($node),
70 'access' => node_access('update', $node),
71 'type' => MENU_LOCAL_TASK,
72 'weight' => 7);
73 }
74 }
75 // we override a menu callback from og.
76 global $user;
77 foreach ($user->og_groups as $key => $sub) {
78 $items[] = array('path' => "og/users/$key",
79 'callback' => 'og2list_list_subscribers_page',
80 'title' => t('subscriber management'),
81 'callback arguments' => array($key),
82 'type' => MENU_CALLBACK,
83 'access' => TRUE);
84 if ($user->og_groups[$key]['is_admin']) {
85 $items[] = array('path' => "og/comments/$key",
86 'callback' => 'og2list_comment_overview',
87 'title' => t('unsent posts'),
88 'callback arguments' => array($key),
89 'type' => MENU_CALLBACK,
90 'access' => TRUE);
91 }
92 }
93 }
94
95 return $items;
96 }
97
98
99 /**
100 * Implementation of hook_cron
101 *
102 * Processing of incoming mail happens here
103 */
104 function og2list_cron() {
105 $lockfile = og2list_lockfile();
106 // obtain lock to prevent corruption
107 $fp = @fopen(file_create_path($lockfile), 'w');
108 if (flock($fp, LOCK_EX)) {
109 // initialize random number generator
110 mt_srand((double)microtime()*1000000);
111 // store the original cron user
112 og2list_switch_user();
113 $result = db_query_range('SELECT c.* FROM {og2list_incoming_groups} g INNER JOIN {og2list_incoming_content} c ON g.mid = c.mid WHERE g.oid != 0 ORDER BY c.mid ASC', 0, variable_get('og2list_incoming_number', 10));
114 while ($mail = db_fetch_object($result)) {
115 $result2 = db_query('SELECT oid FROM {og2list_incoming_groups} WHERE mid = %d', $mail->mid);
116 $mail->og_nids = array();
117
118 while ($group_id = db_fetch_object($result2)) {
119 $mail->og_nids[] = $group_id->oid;
120 }
121 $result3 = db_query('SELECT * FROM {og2list_attachment} WHERE mid = %d', $mail->mid);
122 $mail->attachments = array();
123 while ($attachment = db_fetch_object($result3)) {
124 $filename = tempnam(file_directory_temp(), 'og2list');
125 $fp = fopen($filename, 'w');
126 fwrite($fp, $attachment->payload);
127 fclose($fp);
128 $file = new StdClass();
129 $file->description = $attachment->filename;
130 $file->list = 1;
131 $file->filename = $attachment->filename;
132 $file->filepath = $filename;
133 $file->filemime = $attachment->content_type;
134 $file->filesize = filesize($filename);
135 $file->fid = 'upload_'. $attachment->fid;
136 $mail->files['upload_'. $attachment->fid] = $file;
137 }
138 if (count($mail->og_nids)) {
139 $status = og2list_process_mail($mail);
140 if ($status) {
141 db_query('DELETE FROM {og2list_incoming_content} WHERE mid = %d', $mail->mid);
142 db_query('DELETE FROM {og2list_incoming_groups} WHERE mid = %d', $mail->mid);
143 db_query('DELETE FROM {og2list_attachment} WHERE mid = %d', $mail->mid);
144 }
145 }
146 }
147 if (module_exists('mailcommand')) {
148 $result = db_query_range('SELECT c.* FROM {og2list_incoming_groups} g INNER JOIN {og2list_incoming_content} c ON g.mid = c.mid WHERE g.oid = 0 ORDER BY c.mid ASC', 0, 10);
149 while ($mail = db_fetch_object($result)) {
150 $status = mailcommand_process_mail($mail);
151 if ($status) {
152 db_query('DELETE FROM {og2list_incoming_content} WHERE mid = %d', $mail->mid);
153 db_query('DELETE FROM {og2list_incoming_groups} WHERE mid = %d', $mail->mid);
154 }
155 }
156 }
157 // revert to the original cron user
158 og2list_switch_user();
159 og2list_unlock($fp);
160 }
161 else {
162 watchdog('og2list', t('Could not obtain og2list lock.'), WATCHDOG_ERROR);
163 }
164 }
165
166 /**
167 * Called on shutdown.
168 */
169 function og2list_unlock($fp) {
170 @flock($fp, LOCK_UN);
171 fclose($fp);
172 unlink(og2list_lockfile());
173 }
174
175 function og2list_lockfile() {
176 $temporary_directory = variable_get('file_directory_temp', '/tmp');
177 return $temporary_directory .'/og2list.lock';
178 }
179
180
181 /**
182 * Implementation of hook_settings
183 *
184 */
185 function og2list_admin_settings() {
186 $form['og2list_reserved_addresses'] = array(
187 '#type' => 'textfield',
188 '#title' => t('Reserved addresses'),
189 '#default_value' => variable_get('og2list_reserved_addresses', 'root, postmaster, admin, webmaster, abuse'),
190 '#size' => 70,
191 '#maxlength' => 255,
192 '#description' => t('Local parts of email addresses users may not choose for their mailing lists. Comma-separated list.'),
193 );
194 $form['og2list_domain'] = array(
195 '#type' => 'textfield',
196 '#title' => t('Mail domain'),
197 '#default_value' => variable_get('og2list_domain', $_SERVER['SERVER_NAME']),
198 '#size' => 70,
199 '#maxlength' => 255,
200 '#description' => t('The mail domain used for sending and receiving mail.'),
201 );
202 $form['og2list_ad_hook'] = array(
203 '#type' => 'radios',
204 '#title' => t('Advert placement'),
205 '#default_value' => variable_get('og2list_ad_hook', 'post'),
206 '#options' => array('pre' => t('Before message'), 'post' => t('After message')),
207 '#description' => t('Where adverts should be placed. To actually put adverts into your mail, you will need a module that implements the og2list_ad hook.'),
208 );
209 return system_settings_form($form);
210 }
211
212 /**
213 * Implementaion of hook_form_alter
214 */
215 function og2list_form_alter($form_id, &$form) {
216 $node = $form['#node'];
217
218 if (strpos($form_id, 'node_form') && in_array($node->type, variable_get('og_node_types', array('og')))) {
219 if ( !$node->og2list_ml) {
220 $form['recipient'] = array(
221 '#type' => 'textfield',
222 '#title' => t('Mail address'),
223 '#size' => 60,
224 '#maxlength' => 128,
225 '#description' => t("Optionally specify an mail address for your group's mailing list. For example, if your group's name is 'my friends' type 'my_friends'. Use only lowercase letters, numbers, point, and underscore. You cannot cannot change this address later."),
226 );
227 }
228 else {
229 $form['recipient'] = array(
230 '#type' => 'hidden',
231 '#value' => $node->og2list_ml,
232 );
233 }
234 }
235 if ($form_id == 'og_manage_form') {
236 global $user;
237 $node = node_load((int)arg(2));
238 if ($node->og2list_ml) {
239 $form['address'] = array(
240 '#type' => 'item',
241 '#title' => t('Mail address'),
242 '#value' => theme('placeholder', $node->og2list_ml .'@'. variable_get('og2list_domain', $_SERVER['SERVER_NAME'])),
243 '#description' => t('You can send mail to the group by writing mail this address.'),
244 '#weight' => 0);
245 if ($node->og2list_ml_status && $node->og2list_ml_moderate == 0) {
246 $form['address']['#description'] .= ' '. t('The mailing list is currently enabled and not moderated.');
247 }
248 else if ($node->og2list_ml_status && $node->og2list_ml_moderate == 1) {
249 $form['address']['#description'] .= ' '. t('The mailing list is currently enabled but moderated. The administrator of the list needs to approve each mailed in comment.');
250 }
251 else if (!$node->og2list_ml_status) {
252 $form['address']['#description'] = t('The mailing list is currently disabled.');
253 }
254
255 $form['mail_type'] = array('#type' => 'radios',
256 '#title' => t('Group messages'),
257 '#default_value' => $user->og_groups[(int)arg(2)]['mail_type'],
258 '#options' => array(0 => t('web only'), 1 => t('individual mail'), OG2LIST_OUTGOING_DIGEST => t('digest')),
259 '#description' => t('Do you want to receive mails from this group? You can chose between one mail per post or receive them batched once per day.'),
260 '#weight' => 1);
261 $form['op']['#weight'] = 10;
262 }
263 else {
264 unset($form['mail_type'], $form['op']);
265 $form['not_defined'] = array(
266 '#type' => 'item',
267 '#title' => t('Mail address'),
268 '#value' => t('n/a'),
269 '#description' => t('No mailing list has been created for this group.'),
270 '#weight' => 2);
271 }
272 }
273 }
274
275 /**
276 * Implementation of hook_nodeapi
277 *
278 */
279 function og2list_link($type, $node = 0, $main = 0) {
280 $links = array();
281
282 if ($type == 'comment') {
283 if (node_comment_mode($comment->nid) == COMMENT_NODE_READ_WRITE) {
284 global $user;
285 // avoid adding the link where it already exists
286 if (!user_access('administer comments') && user_access('post comments') &&$comment->uid != $user->uid) {
287 $node = node_load($comment->nid);
288 if (!isset($user->og_groups)) {
289 $user = user_load(array('uid' => $user->uid));
290 }
291 $groups = array_intersect($node->og_groups, array_keys($user->og_groups));
292 foreach ($groups as $gid) {
293 if ($user->og_groups[$gid]['is_admin'] == 1) {
294 $links['og2list_comment_edit'] = array('title' => t('edit'), 'href' => 'comment/edit/'.$comment->cid);
295 break;
296 }
297 }
298 }
299 }
300 }
301
302 return $links;
303 }
304
305 /**
306 * Implementation of hook_og_create_links
307 *
308 */
309 function og2list_og_create_links($node){
310 global $user;
311 if (!isset($user->og_groups)) {
312 $user = user_load(array('uid' => $user->uid));
313 }
314 if ($user->og_groups[$node->nid]['is_admin'] == 1) {
315 $links[] = l(t('unpublished comments'), "og/comments/$node->nid");
316 }
317 return $links ? $links : array();
318 }
319
320 /**
321 * Implementation of hook_nodeapi
322 *
323 */
324 function og2list_nodeapi(&$node, $op, $arg = 0) {
325 switch ($op) {
326 case 'load':
327 if (og_is_group_type($node->type)) {
328 $result = db_fetch_array(db_query("SELECT recipient, status, moderate, prefix FROM {og2list_groups} WHERE nid = %d", $node->nid));
329 $node->og2list_ml = $result['recipient'];
330 $node->og2list_ml_status = $result['status'];
331 $node->og2list_ml_moderate = $result['moderate'];
332 $node->og2list_subject_prefix = $result['prefix'];
333 }
334 break;
335 case 'validate':
336 // validate the given mail address
337 if (og_is_group_type($node->type)) {
338 $user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\']+';
339 if (isset($node->recipient) && strlen($node->recipient) > 0 && !preg_match("/^$user$/", $node->recipient)) {
340 form_set_error('recipient', t('The chosen address contains illegal characters.'));
341 }
342 if ($node->nid) {
343 $count = db_num_rows(db_query("SELECT recipient FROM {og2list_groups} WHERE LOWER(recipient) = '%s' AND nid != %d", strtolower($node->recipient), $node->nid));
344 }
345 else {
346 $count = db_num_rows(db_query("SELECT recipient FROM {og2list_groups} WHERE LOWER(recipient) = '%s'", strtolower($node->recipient)));
347 }
348 if ($count && $count > 0) {
349 // mail address already in use.
350 form_set_error('recipient', t('The chosen address is already in use by another group.'));
351 }
352
353 if (in_array($node->recipient, array_map('trim', explode(',', variable_get('og2list_reserved_addresses', 'root, postmaster, admin, webmaster, abuse'))))) {
354 form_set_error('recipient', t('The chosen address is reserved.'));
355 }
356 }
357 break;
358 case 'insert':
359 if (og_is_group_type($node->type)) {
360 if (isset($node->recipient) && strlen($node->recipient) && $node->nid) {
361 $count = db_num_rows(db_query("SELECT nid FROM {og2list_groups} WHERE nid = %d",$node->nid));
362 if ($count && $count > 0) { // old row exists, delete it.
363 db_query("DELETE FROM {og2list_groups} where nid = %d",$node->nid);
364 }
365 db_query("INSERT INTO {og2list_groups} (nid, recipient, status) VALUES (%d, '%s', 1)", $node->nid, $node->recipient);
366 }
367 }
368 else {
369 $edit = (array) $node;
370 if(count($edit['og_groups'])) {
371 $edit['og_nids'] = $edit['og_groups'];
372 // Find the lists to send to.
373 og2list_get_groups($edit);
374 }
375 if (count($edit['ogs'])) {
376 og2list_send_mail($edit);
377 }
378 }
379 break;
380 case 'update':
381 // If the node previously did not have an address and one has just been assigned,
382 // then we need to set it now. If the node did have an og2list_groups row before
383 // then the recipient wasn't set and we update it. For now you still cannot change
384 // a recipient once it's set.
385 //
386 if ($node->recipient && (db_num_rows(db_query("SELECT recipient FROM {og2list_groups} WHERE nid = %d", $node->nid)) == 0)) {
387 db_query("INSERT INTO {og2list_groups} (nid, recipient, status) VALUES(%d, '%s', 1)", $node->nid, $node->recipient);
388 }
389
390 if ($node->status == 1) {
391 db_query('UPDATE {og2list_outgoing_arguments} a INNER JOIN {og2list_outgoing_content} c ON a.mid = c.mid SET a.status = %d WHERE c.is_node = 1 AND c.id = %d AND a.status = %d', OG2LIST_OUTGOING_NOT_SENT, $node->nid, OG2LIST_OUTGOING_MODERATED);
392 }
393 break;
394 }
395 }
396
397 /**
398 * Called by comment.module after working on a comment.
399 * Sends comments to specified addresses.
400 *
401 * $comment: Array containing the comment.
402 * Important fields:
403 * $comment['subject']: Oh well.
404 * $comment['comment']: The text
405 * $comment['nid']: commented node id
406 * $comment['cid']: comment id
407 * $comment['pid']: cid of parent
408 * $comment['uid']: user id
409 * $comment['status']: status of comment
410 *
411 * $op: type of call, here insert is expected.
412 *
413 */
414 function og2list_comment($comment, $op) {
415 switch ($op) {
416 case 'insert':
417 $node = (array) node_load($comment['nid']);
418
419 if(count($node['og_groups'])) {
420 $comment['og_nids'] = $node['og_groups'];
421 // Find the lists to send to.
422 og2list_get_groups($comment);
423 }
424 if (count($comment['ogs'])) {
425 og2list_send_mail($comment);
426 }
427 break;
428 case 'update':
429 if ($comment['status'] != COMMENT_PUBLISHED) {
430 return;
431 }
432 $cid = $comment['cid'];
433 // no break
434 case 'publish':
435 $cid = $cid ? $cid : $comment->cid;
436 db_query('UPDATE {og2list_outgoing_arguments} a INNER JOIN {og2list_outgoing_content} c ON a.mid = c.mid SET a.status = %d WHERE c.is_node = 0 AND c.id = %d AND a.status = %d', OG2LIST_OUTGOING_NOT_SENT, $cid, OG2LIST_OUTGOING_MODERATED);
437 break;
438 }
439 }
440
441 function og2list_send_mail($edit) {
442 // If a comment or node was generated by moving stuff around with
443 // comment_mover we do not want to mail it.
444 if (isset($edit['comment_mover'])) {
445 return;
446 }
447 // Formatting
448 if (!isset($edit['body'])) { // comment posted
449 global $user;
450 $body = $edit['comment'];
451 $body = check_markup($body, $edit['format']);
452 $subject = strip_tags($edit['subject']);
453 // try to get parent's references.
454 og2list_get_references($edit);
455 if ($user->uid != $edit['uid']) {
456 $account = user_load(array('uid' => $edit['uid']));
457 }
458 else {
459 $account = $user;
460 }
461 $status = user_access('post comments without approval', $account) ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED;
462 $status = ($status == COMMENT_PUBLISHED) ? 1 : 0;
463 }
464 else { // node posted
465 $body = $edit['body'];
466 $body = check_markup($body, $edit['format']);
467 $subject = strip_tags($edit['title']);
468 $edit['cid'] = 0;
469 $status = $edit['status'];
470 $rows = array();
471 if (isset($edit['files'])) {
472 switch (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) {
473 case FILE_DOWNLOADS_PUBLIC:
474 $files = $edit['files'];
475 break;
476 case FILE_DOWNLOADS_PRIVATE:
477 // upload.module needs to be run before og2list.
478 $node = node_load($edit['nid']);
479 $files = $node->files;
480 break;
481 }
482
483 foreach ($files as $file) {
484 // Convert file to object for compatibility
485 $file = (object)$file;
486
487 if ($file->list) {
488 $rows[] = array(
489 '<a href="'. check_url(($file->fid ? file_create_url($file->filepath) : url(file_create_filename($file->filename, file_create_path()), NULL, NULL, TRUE))) .'">'. check_plain($file->filename) .'</a>',
490 format_size($file->filesize)
491 );
492 }
493 }
494 if (count($rows)) {
495 $body .= t('Attached files:');
496 $body .= theme_table(array(), $rows);
497 }
498 }
499 }
500 $account = user_load(array('uid' => $edit['uid']));
501
502 $ad = module_invoke_all('og2list_ad', $edit);
503
504 if (variable_get('og2list_ad_hook', 'post') == 'post') {
505 $body .= implode("\n", $ad);
506 }
507 else {
508 $body = implode("\n", $ad) . $body;
509 }
510
511 if(!$account->uid) {
512 $edit['name'] = check_plain(variable_get('anonymous', 'Anonymous'));
513 $edit['mail'] = check_plain(variable_get('og2list_from', variable_get('site_mail', 'root@localhost')));
514 }
515 else {
516 $edit['name'] = check_plain($account->name);
517 $edit['mail'] = check_plain($account->mail);
518 }
519
520 // if we got invoked from cron we already got msg-id and references stored.
521 if (!og2list_test_cron()) {
522 $msg_id = '<'. time() .'.'. mt_rand() .'@'. strtolower(variable_get('og2list_domain', $_SERVER['SERVER_NAME'])) .'>';
523 db_query("INSERT INTO {og2list_msgid} (nid, cid, msgid) VALUES (%d, %d, '%s')", $edit['nid'], $edit['cid'], $msg_id);
524
525 if (isset($edit['references']) && count($edit['references'])) {
526 $arguments = array();
527 $values = array();
528 foreach ($edit['references'] as $reference) {
529 $arguments[] = " ('%s', '%s')";
530 $values = array_merge($values, array($msg_id, $reference));
531 }
532 db_query('INSERT INTO {og2list_references} (msgid, reference) VALUES '. implode(',', $arguments), $values);
533 }
534 }
535 else {
536 $msg_id = db_result(db_query('SELECT msgid FROM {og2list_msgid} WHERE nid = %d AND cid = %d', $edit['nid'], $edit['cid']));
537 }
538
539 // save in og2list outgoing table.
540 foreach($edit['og_nids'] as $og) {
541 $node = node_load($og);
542 $subject = $node->og2list_subject_prefix .' '. $subject;
543 $mid = db_next_id("{og2list_outgoing_content}_mid");
544 db_query("INSERT INTO {og2list_outgoing_content} (mid, to_name, to_address, from_name, from_address, subject, msgid, body, is_node, id) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)", $mid, $edit['ogs'][$og]['name'], $edit['ogs'][$og]['address'], $edit['name'], $edit['mail'], $subject, $msg_id, "<html><body>$body</body></html>", $edit['cid'] ? 0 : 1, $edit['cid'] ? $edit['cid'] : $edit['nid']);
545
546 // see og2list.install for status codes
547 $result = db_query('INSERT INTO {og2list_outgoing_arguments} (mid, nid, timestamp, status, uid) VALUES (%d, %d, %d, %d, %d)', $mid, $og, time(), $node->og2list_ml_status ? (($node->og2list_ml_moderate || ($status == 0)) ? OG2LIST_OUTGOING_MODERATED : OG2LIST_OUTGOING_NOT_SENT) : OG2LIST_OUTGOING_POSTPONED, $account->uid);
548 }
549 }
550
551 /**
552 * process incoming mail
553 *
554 * @param $mail mail object
555 */
556 function og2list_process_mail($mail) {
557 $result = db_query("SELECT m.* FROM {og2list_msgid} m INNER JOIN {og2list_references} r ON m.msgid = r.reference WHERE r.msgid = '%s'", $mail->msgid);
558 switch (db_num_rows($result)) {
559 case 0:
560 // a new message, no parent found. Post as node.
561 if ($uid = og2list_find_user($mail)) {
562 $node = new StdClass();
563 $node->uid = $uid;
564 $node->type = 'forum';
565 $node->comment = 2;
566 $node_options = variable_get('node_options_forum', array('status', 'promote'));
567 $node->status = user_access('create forum topics', $user) ? in_array('status', $node_options) : 0;
568 $node->og_groups = $mail->og_nids;
569 if ($mail->files) {
570 $node->files = $mail->files;
571 }
572
573 $node->taxonomy = array();
574 foreach ($mail->og_nids as $oid) {
575 $og = node_load($oid);
576 // strip prefix from subject
577 $mail->subject = str_replace($og->og2list_subject_prefix, '', $mail->subject);
578 if ($og->og2list_ml_moderate) {
579 // if a single list is moderated, it applies to all OGs.
580 $node->status = 0;
581 }
582 $node->taxonomy[] = _og2list_og_forum_get_forum($oid);
583 }
584 // The first matching groups "owns" the post.
585 $node->tid = $node->taxonomy[0];
586 $node->title = $mail->subject;
587 switch($mail->content_type) {
588 case 'text/plain':
589 $node->format = 1;
590 $node->body = $mail->body;
591 break;
592 case 'text/html':
593 $node->format = 1;
594 $node->body = $mail->body;
595 break;
596 default:
597 watchdog('og2list', t('Unknown mime type in message with message id %msgid. Message held.', array('%msgid' => filter_xss($mail->msgid))), WATCHDOG_WARNING);
598 return FALSE;
599 break;
600 }
601 node_save($node);
602 if ($node->nid) {
603 return TRUE;
604 }
605 else {
606 watchdog('og2list', t('Error saving node for message with message id %msgid. Message held.', array('%msgid' => filter_xss($mail->msgid))), WATCHDOG_WARNING);
607 return FALSE;
608 }
609 }
610 else {
611 // no user found, discard message.
612 return TRUE;
613 }
614 break;
615 case 1:
616 // found a parent message. Post as comment.
617 if ($uid = og2list_find_user($mail)) {
618 $reference = db_fetch_array($result);
619 $comment = array();
620 $comment['uid'] = $uid;
621 $comment['nid'] = $reference['nid'];
622 $comment['pid'] = $reference['cid'];
623 $comment['subject'] = $mail->subject;
624 $comment['status'] = user_access('post comments without approval', $user) ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED;
625 foreach ($mail->og_nids as $oid) {
626 $og = node_load($oid);
627 if ($og->og2list_ml_moderate) {
628 // if a single list is moderated, it applies to all OGs.
629 $comment['status'] = COMMENT_NOT_PUBLISHED;
630 }
631 }
632 switch($mail->content_type) {
633 case 'text/plain':
634 $comment['comment'] = $mail->body;
635 $comment['format'] = 1;
636 break;
637 case 'text/html':
638 $comment['comment'] = $mail->body;
639 $comment['format'] = 1;
640 break;
641 default:
642 watchdog('og2list', t('Unknown mime type in message with message id %msgid. Message held.', array('%msgid' => filter_xss($mail->msgid))), WATCHDOG_WARNING);
643 return FALSE;
644 break;
645 }
646 return comment_save($comment);
647 }
648 else {
649 // no user found, discard message.
650 return TRUE;
651 }
652 break;
653 default:
654 // more than one parent, must be a bug
655 watchdog('og2list', t('Found more than one parent for a mail with message id %msgid. Message held.', array('%msgid' => filter_xss($mail->msgid))), WATCHDOG_WARNING);
656 return FALSE;
657 }
658 return FALSE;
659 }
660
661 /**
662 * overview screen for admins
663 */
664 function og2list_admin() {
665 print 'Here could be a nice overview screen for existing MLs, how many users they have, etc. Potentially also overview for the Mail queue.';
666 }
667
668 /**
669 * Menu callback, overview screen of group subscribers. Hitchhiked from
670 * og.module
671 */
672 function og2list_list_subscribers_page ($gid) {
673 $header[] = t("Name");
674 $node = node_load($gid);
675 $access = node_access('update', $node);
676 if ($access) {
677 $header[] = array('data' => t('Operations'), 'colspan' => 2);
678 }
679 // prepend the group manager
680 $i=0;
681 $rows[$i][] = theme('username', $node). '&nbsp;<em>'. t('manager'). '</em>';
682 if ($access) {
683 $rows[$i][] = l(t('edit group'), "node/$gid/edit");
684 $rows[$i][] = '&nbsp;';
685 }
686 $i++;
687
688 $sql = og_list_users_sql(0);
689 $result = pager_query($sql, 500, 0, NULL, $gid);
690 while ($account = db_fetch_object($result)) {
691 if ($account->uid != $node->uid) {
692 $rows[$i][] = theme('username', $account);
693 if ($access) {
694 if ($account->is_active) {
695 $rows[$i][] = l(t('unsubscribe'), "og/unsubscribe/$gid/$account->uid", array(), "destination=og/users/$gid");
696 if ($account->is_admin) {
697 $rows[$i][] = l(t('admin: remove'), "og/delete_admin/$gid/$account->uid", array(), 'destination='. $_GET['q']);
698 }
699 else {
700 $rows[$i][] = l(t('admin: create'), "og/create_admin/$gid/$account->uid", array(), 'destination='. $_GET['q']);
701 }
702 }
703 else {
704 $rows[$i][] = l(t('approve'), "og/approve/$gid/$account->uid", array(), "destination=og/users/$gid");
705 $rows[$i][] = l(t('deny'), "og/deny/$gid/$account->uid", array(), "destination=og/users/$gid");
706 }
707 }
708 $i++;
709 }
710 }
711 if ($pager = theme('pager', NULL, 500)) {
712 $rows[$i][] = array('data' => $pager, 'colspan' => 2);
713 }
714 $output = theme('table', $header, $rows);
715 $bc = array(l(t('Home'), ''), l(t('groups'), 'og'), l($node->title, "node/$node->nid"));
716 drupal_set_breadcrumb($bc);
717 drupal_set_title(t('Subscribers'). ': '. l($node->title, "node/$node->nid"));
718 return $output;
719 }
720
721 /**
722 * Menu callback, comment_edit function. Hitchhiked from
723 * comment.module
724 */
725 function og2list_comment_edit($cid) {
726 global $user;
727
728 $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d', $cid));
729 $comment = drupal_unpack($comment);
730 $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
731 if (comment_access('edit', $comment)) {
732 return comment_form_box((array)$comment);
733 }
734 else if (($user = user_load(array('uid' => $user->uid))) && ($node = node_load($comment->nid)) && $groups = array_intersect($node->og_groups, array_keys($user->og_groups))) {
735 foreach ($groups as $gid) {
736 if ($user->og_groups[$gid]['is_admin'] == 1) {
737 return comment_form_box((array) $comment);
738 break;
739 }
740 }
741 }
742 else {
743 drupal_access_denied();
744 }
745 }
746
747 /**
748 * Menu callback; present an administrative comment listing per group.
749 */
750 function og2list_comment_overview($gid) {
751 $edit = $_POST['edit'];
752 global $user;
753 if (!isset($user->og_groups)) {
754 $user = user_load(array('uid' => $user->uid));
755 }
756 if ($user->og_groups[$gid]['is_admin'] != 1) {
757 drupal_access_denied();
758 }
759
760 if ($edit['operation'] == 'delete') {
761 return og2list_comment_multiple_delete_confirm();
762 }
763
764 // build an 'Update options' form
765 $form['options'] = array(
766 '#type' => 'fieldset', '#title' => t('Update options'),
767 '#prefix' => '<div class="container-inline">', '#suffix' => '</div>'
768 );
769 $options = array();
770 foreach (comment_operations('publish') as $key => $value) {
771 $options[$key] = $value[0];
772 }
773 $form['options']['operation'] = array('#type' => 'select', '#options' => $options, '#default_value' => 'publish');
774 $form['options']['submit'] = array('#type' => 'submit', '#value' => t('Update'));
775
776 // load the comments that we want to display
777 $status = COMMENT_NOT_PUBLISHED;
778 $form['header'] = array('#type' => 'value', '#value' => array(
779 NULL,
780 array('data' => t('Subject'), 'field' => 'subject'),
781 array('data' => t('Author'), 'field' => 'name'),
782 array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'),
783 array('data' => t('Operations'))
784 ));
785 $result = pager_query('SELECT c.subject, c.nid, c.cid, c.comment, c.timestamp, c.status, c.name, c.homepage, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid INNER JOIN {node_access} na ON c.nid = na.nid WHERE c.status = %d AND na.gid = %d'. tablesort_sql($form['header']['#value']), 50, 0, NULL, $status, $gid);
786
787 // build a table listing the appropriate comments
788 $destination = drupal_get_destination();
789 while ($comment = db_fetch_object($result)) {
790 $comments[$comment->cid] = '';
791 $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
792 $form['subject'][$comment->cid] = array('#value' => l($comment->subject, 'node/'. $comment->nid, array('title' => truncate_utf8($comment->comment, 128)), NULL, 'comment-'. $comment->cid));
793 $form['username'][$comment->cid] = array('#value' => theme('username', $comment));
794 $form['timestamp'][$comment->cid] = array('#value' => format_date($comment->timestamp, 'small'));
795 $form['operations'][$comment->cid] = array('#value' => l(t('edit'), 'comment/edit/'. $comment->cid, array(), $destination));
796 }
797 $form['comments'] = array('#type' => 'checkboxes', '#options' => $comments);
798 $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
799 $form['gid'] = array('#type' => 'hidden', '#value' => $gid);
800 return drupal_get_form('og2list_comment_overview', $form);
801 }
802
803 /**
804 * We can't execute any 'Update options' if no comments were selected.
805 */
806 function og2list_comment_overview_validate($form_id, $form_values) {
807 $form_values['comments'] = array_diff($form_values['comments'], array(0));
808 if (count($form_values['comments']) == 0) {
809 form_set_error('', t('Please select one or more comments to perform the update on.'));
810 drupal_goto('og/comments/'. $form_values['gid']);
811 }
812 }
813
814 function theme_og2list_comment_overview($form) {
815 $output = form_render($form['options']);
816 if (isset($form['subject']) && is_array($form['subject'])) {
817 foreach (element_children($form['subject']) as $key) {
818 $row = array();
819 $row[] = form_render($form['comments'][$key]);
820 $row[] = form_render($form['subject'][$key]);
821 $row[] = form_render($form['username'][$key]);
822 $row[] = form_render($form['timestamp'][$key]);
823 $row[] = form_render($form['operations'][$key]);
824 $rows[] = $row;
825 }
826 }
827 else {
828 $rows[] = array(array('data' => t('No comments available.'), 'colspan' => '6'));
829 }
830
831 $output .= theme('table', $form['header']['#value'], $rows);
832 if ($form['pager']['#value']) {
833 $output .= form_render($form['pager']);
834 }
835
836 $output .= form_render($form);
837
838 return $output;
839 }
840
841 /**
842 * Execute the chosen 'Update option' on the selected comments, such as
843 * publishing, unpublishing or deleting.
844 */
845 function og2list_comment_overview_submit($form_id, $form_values) {
846 $operations = comment_operations();
847 if ($operations[$form_values['operation']][1]) {
848 // extract the appropriate database query operation
849 $query = $operations[$form_values['operation']][1];
850 foreach ($form_values['comments'] as $cid => $value) {
851 if ($value) {
852 // perform the update action, then refresh node statistics
853 db_query($query, $cid);
854 $comment = _comment_load($cid);
855 _comment_update_node_statistics($comment->nid);
856 // Allow modules to respond to the updating of a comment.
857 comment_invoke_comment($comment, $form_values['operation']);
858 // Add an entry to the watchdog log.
859 watchdog('content', t('Comment: updated %subject.', array('%subject' => theme('placeholder', $comment->subject))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $comment->nid, NULL, NULL, 'comment-'. $comment->cid));
860 }
861 }
862 cache_clear_all();
863 drupal_set_message(t('The update has been performed.'));
864 drupal_goto('og/comments/'. $form_values['gid']);
865 }
866 }
867
868 /**
869 * List the selected comments and verify that the admin really wants to delete
870 * them.
871 */
872 function og2list_comment_multiple_delete_confirm() {
873 $edit = $_POST['edit'];
874
875 $form['comments'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
876 // array_filter() returns only elements with actual values
877 $comment_counter = 0;
878 foreach (array_filter($edit['comments']) as $cid => $value) {
879 $comment = _comment_load($cid);
880 if (is_object($comment) && is_numeric($comment->cid)) {
881 $subject = db_result(db_query('SELECT subject FROM {comments} WHERE cid = %d', $cid));
882 $form['comments'][$cid] = array('#type' => 'hidden', '#value' => $cid, '#prefix' => '<li>', '#suffix' => check_plain($subject) .'</li>');
883 $comment_counter++;
884 }
885 }
886 $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
887
888 if (!$comment_counter) {
889 drupal_set_message(t('There do not appear to be any comments to delete or your selected comment was deleted by another administrator.'));
890 drupal_goto('og/comments/'. $edit['gid']);
891 }
892 else {
893 return confirm_form('og2list_comment_multiple_delete_confirm', $form,
894 t('Are you sure you want to delete these comments and all their children?'),
895 'og/comments/'. $edit['gid'], t('This action cannot be undone.'),
896 t('Delete comments'), t('Cancel'));
897 }
898 }
899
900 /**
901 * Perform the actual comment deletion.
902 */
903 function og2list_comment_multiple_delete_confirm_submit($form_id, $edit) {
904 if ($edit['confirm']) {
905 foreach ($edit['comments'] as $cid => $value) {
906 $comment = _comment_load($cid);
907 _comment_delete_thread($comment);
908 _comment_update_node_statistics($comment->nid);
909 cache_clear_all();
910 }
911 drupal_set_message(t('The comments have been deleted.'));
912 }
913 drupal_goto('og/comments/'. $edit['edit']);
914 }
915
916 /**
917 * Menu callback; present an administrative comment listing per group.
918 */
919 function og2list_posts_overview($gid) {
920 $edit = $_POST['edit'];
921 global $user;
922 if (!isset($user->og_groups)) {
923 $user = user_load(array('uid' => $user->uid));
924 }
925 if ($user->og_groups[$gid]['is_admin'] != 1) {
926 drupal_access_denied();
927 }
928
929 if ($edit['operation'] == 'delete') {
930 return og2list_comment_multiple_delete_confirm();
931 }
932
933 // build an 'Update options' form
934 $form['options'] = array(
935 '#type' => 'fieldset', '#title' => t('Update options'),
936 '#prefix' => '<div class="container-inline">', '#suffix' => '</div>'
937 );
938 $options = array();
939 foreach (comment_operations('publish') as $key => $value) {
940 $options[$key] = $value[0];
941 }
942 $form['options']['operation'] = array('#type' => 'select', '#options' => $options, '#default_value' => 'publish');
943 $form['options']['submit'] = array('#type' => 'submit', '#value' => t('Update'));
944
945 // load the comments that we want to display
946 $form['header'] = array('#type' => 'value', '#value' => array(
947 NULL,
948 array('data' => t('Subject'), 'field' => 'subject'),
949 array('data' => t('Author'), 'field' => 'name'),
950 array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'),
951 array('data' => t('Post status'), 'field' => 'status', 'sort' => 'desc'),
952 array('data' => t('Sent status'), 'field' => 'og2list_status', 'sort' => 'desc'),
953 array('data' => t('Operations'))
954 ));
955
956 $result = pager_query('SELECT oa.mid, oa.status AS og2list_status, u.name AS registered_name, u.uid, IF(oc.is_node, 0, c.cid) AS cid, c.name, IF(oc.is_node, n.changed, c.timestamp) AS timestamp, IF(oc.is_node, n.status, c.status) AS status, IF(oc.is_node, n.nid, c.nid) AS nid, IF(oc.is_node, n.title, c.subject) AS title, oc.is_node FROM {og2list_outgoing_arguments} oa INNER JOIN {node_access} na ON na.gid = oa.nid INNER JOIN {og2list_outgoing_content} oc ON oc.mid = oa.mid INNER JOIN {users} u ON oa.uid = u.uid LEFT JOIN {comments} c ON oc.id = c.cid LEFT JOIN {node} n ON oc.id = n.nid WHERE oa.status = %d AND na.gid = %d GROUP BY oa.mid'. tablesort_sql($form['header']['#value']), 50, 0, NULL, OG2LIST_OUTGOING_MODERATED, $gid);
957
958 // build a table listing the appropriate comments
959 $destination = drupal_get_destination();
960 while ($post = db_fetch_object($result)) {
961 $id = $post->mid;
962 $posts[$id] = '';
963 $post->name = $post->uid ? $post->registered_name : $post->name;
964 $form['subject'][$id] = array('#value' => l($post->title, 'node/'. $post->nid, NULL, $post->is_node ? NULL : 'comment-'. $post->cid));
965 $form['username'][$id] = array('#value' => theme('username', $post));
966 $form['timestamp'][$id] = array('#value' => format_date($post->timestamp, 'small'));
967 $form['status'][$id] = array('#value' => $post->status);
968 $form['og2list_status'][$id] = array('#value' => $post->og2list_status);
969 $form['operations'][$id] = array('#value' => l(t('edit'), $post->is_node ? "node/$post->nid/edit" : 'comment/edit/'. $post->cid, array(), $destination));
970 }
971 $form['posts'] = array('#type' => 'checkboxes', '#options' => $posts);
972 $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
973 $form['gid'] = array('#type' => 'hidden', '#value' => $gid);
974
975 return drupal_get_form('og2list_posts_overview', $form);
976 }
977
978 /**
979 * We can't execute any 'Update options' if no comments were selected.
980 */
981 function og2list_posts_overview_validate($form_id, $edit) {
982 $edit['posts'] = array_diff($edit['posts'], array(0));
983 if (count($edit['posts']) == 0) {
984 form_set_error('', t('Please select one or more posts to perform the update on.'));
985 drupal_goto('og/comments/'. $edit['gid']);
986 }
987 }
988
989 function theme_og2list_posts_overview($form) {
990 $output = form_render($form['options']);
991 if (isset($form['subject']) && is_array($form['subject'])) {
992 foreach (element_children($form['subject']) as $key) {
993 $row = array();
994 $row[] = form_render($form['posts'][