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

Contents of /contributions/modules/views_mail/views_mail.module

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


Revision 1.1 - (show annotations) (download) (as text)
Tue Jun 5 22:46:12 2007 UTC (2 years, 5 months ago) by somebodysysop
Branch: MAIN
CVS Tags: DRUPAL-5--1-1, DRUPAL-5--1-0, HEAD
Branch point for: DRUPAL-5
File MIME type: text/x-php
Initial views_mail distribution.
1 <?php
2 /**
3 * @file
4 * Mail to a group as selected by a views view
5 *
6 * @todo
7 *
8 * - set up userreference and nodereference fields to use the name and email of the userreference and nodereference uid
9 * - incorporate Token module to handle substitutions
10 * - scheduling does nothing right now, all mail is sent immediately, add hook into actions module to schedule mail
11 * - add logging of sent emails, either name and date or name, date and message, that can be sorted and viewed by recipient and/or sender
12 * - wouldn't mind just creating the messages and sending them off to some other module to handle the mailing and logging
13 */
14
15 /**
16 * Implementation of hook_help().
17 */
18 function views_mail_help($section) {
19 switch ($section) {
20 case 'admin/help#description':
21 return views_mail_helptext();
22 case 'admin/settings/views_mail':
23 return views_mail_helptext();
24 }
25 }
26
27 function views_mail_helptext() {
28 $description = t('All views that have Views Mail selected as a page type will have a collapsed fieldset above the view that contains an email message form. The message form will be displayed only to users with permissions to send mail.');
29 $description .= t('<p>Views Mail views should include fields for each value that will be used as recipient names or addresses and any values that can be substituted into the email message itself. Give each field a unique and descriptive label.</p>');
30 $description .= t('<p>Mail will only be sent to recipients in the visible page of multi-page views. You may want to adjust your view settings to be sure that the records that should be mailed to are visible on the same page. </p>');
31 return $description;
32 }
33
34 /**
35 * Implementation of hook_perm().
36 */
37 function views_mail_perm() {
38 return array('send views mail');
39 }
40
41 function views_mail_menu($may_cache) {
42 $items = array();
43 if ($may_cache) {
44 $items[] = array(
45 'path' => 'admin/settings/views_mail',
46 'title' => t('Views mail configuration'),
47 'description' => t('Configure email capabilities for Views.'),
48 'callback' => 'views_mail_settings',
49 'access' => user_access('send views mail'),
50 'type' => MENU_NORMAL_ITEM,
51 );
52 }
53 return $items;
54 }
55
56 /**
57 * Implementation of hook_settings()
58 */
59 function views_mail_settings() {
60 return drupal_get_form('views_mail_settings_form');
61 }
62
63 /**
64 * Create alias fields in the view for to_name and to_mail
65 */
66 function views_mail_views_query_alter(&$query, &$view, $summary, $level) {
67 if ($view->page_type == 'views_mail' && !$summary
68 && ($view->build_type == 'page' || $view->build_type == 'items')
69 && user_access('send views mail')) {
70 return _views_mail_query_alter($query, $view, $summary, $level);
71 }
72 }
73
74 /**
75 * Implementation of hook_user().
76 *
77 * Provide form element to opt in to content mailouts.
78 */
79 function views_mail_user($type, $edit, &$user, $category = NULL) {
80 if ($type == 'register' || ($type == 'form' && $category == 'account')) {
81 $form['views_mail'] = array(
82 '#type' => 'fieldset',
83 '#title' => t('Group e-mail settings'),
84 '#weight' => 5,
85 '#collapsible' => TRUE,
86 );
87
88 // Force checkbox to default on if this is first time registration;
89
90 if ($type == 'register') {
91
92 // If force group email setting, then hide group e-mail settings checkbox on registration
93 // because it will default to "on".
94
95 $type = 'checkbox';
96 $opt_in = variable_get("views_mail_force_mail_accept", 0);
97 if ($opt_in == 1) $type = 'hidden';
98
99 $form['views_mail']['views_mail_accept'] = array(
100 '#type' => $type,
101 '#title' => t('Accept email'),
102 '#default_value' => 1,
103 '#description' => t('Allow yourself to be included in group e-mails from privileged users. Note that your e-mail address is not made public and that site administrators are able to email you even if you choose not to enable this feature.'),
104 );
105 } else {
106 $form['views_mail']['views_mail_accept'] = array('#type' => 'checkbox',
107 '#title' => t('Accept email'),
108 '#default_value' => $edit['views_mail_accept'],
109 '#description' => t('Allow yourself to be included in group e-mails from privileged users. Note that your e-mail address is not made public and that site administrators are able to email you even if you choose not to enable this feature.'),
110 );
111 }
112
113 return $form;
114 } // end register if
115
116 if ($type == 'validate') {
117 return array('views_mail_accept' => $edit['views_mail_accept']);
118 } // end validate if
119
120 if ($type == "insert") {
121 // Subscribe this user to the newsletter if it exists
122 $str = variable_get("views_mail_subscribe_newsletter", '');
123 if (!empty($str)) {
124 $array = preg_split('/\|/', $str, -1, PREG_SPLIT_NO_EMPTY); // split at the | = newsletter | comment
125 if (!empty($array)) {
126 $newsletter = $array[0];
127 simplenews_subscribe_user($user->mail, $newsletter, $confirm = FALSE);
128 } // end if
129 } // end if
130 } // end insert if
131
132 }
133
134
135 /**
136 * Implementation of hook_views_style_plugins()
137 */
138 function views_mail_views_style_plugins() {
139 $plugins['views_mail'] = array(
140 'name' => t('Views mail'),
141 'theme' => 'views_mail_display',
142 'needs_fields' => TRUE,
143 'needs_table_header' => TRUE,
144 );
145 return $plugins;
146 }
147
148 /**
149 * Calendar Views plugin theme, overrides default views theme
150 */
151 function theme_views_mail_display(&$view, &$items, $type) {
152 // TODO - if this is only a partial view, may want to enlarge view
153 if ($view->use_pager && sizeof($items) == $view->nodes_per_page) {
154 // for now doing nothing and only mailing to the visible portion of the view
155 }
156 $output = drupal_get_form('views_mail_mail_form', $view, $items);
157 // In later steps we want to hide $items and only display info about the mail recipients.
158 if ($_SESSION['views_mail']['step'] < 2) {
159 $view->table_header = _views_construct_header($view, _views_get_fields());
160 $output .= theme('views_view_table', $view, $items, $type);
161 }
162 return $output;
163 }
164
165 /**
166 * The Views Mail settings form.
167 *
168 * @return array $form
169 */
170 function views_mail_settings_form() {
171 $form['#suffix'] = $explanation;
172
173 $form['default settings'] = array(
174 '#type' => 'fieldset',
175 '#title' => t('Settings'),
176 '#weight' => -20,
177 );
178 $form['default settings']['views_mail_email_default_newsletter'] = array(
179 '#type' => 'select',
180 '#title' => t('Default newsletter'),
181 '#default_value' => variable_get('views_mail_email_default_newsletter', ''),
182 '#options' => views_mail_default_newsletters(),
183 '#description' => t('The default newsletter which contains the newsletter issues that Views Mail will select from.'),
184 '#required' => TRUE,
185 );
186
187 $form['option settings'] = array(
188 '#type' => 'fieldset',
189 '#title' => t('Options'),
190 '#weight' => -15,
191 );
192 $form['option settings']['views_mail_force_mail_accept'] = array(
193 '#type' => 'checkbox',
194 '#title' => t('Force group e-mail opt-in'),
195 '#default_value' => variable_get('views_mail_force_mail_accept', 0),
196 '#description' => t('When new user signs up, force the group e-mail opt-in to be checked, even if user unchecks it on signup.')
197 );
198 $form['option settings']['views_mail_subscribe_newsletter'] = array(
199 '#type' => 'textarea',
200 '#title' => t('Subscribe all new signups to newsletter'),
201 '#default_value' => variable_get('views_mail_subscribe_newsletter', ''),
202 '#cols' => 80,
203 '#rows' => 1,
204 '#description' => t('Specify here the Simplenews newsletter ID number to which you want ALL new signups
205 to be subscribed. You only need to enter the newsletter ID (TID) number. If no number is entered
206 here, then new signups to the site will not be automatically subscribed to a newsletter. If a number
207 is entered here, then all new signups to the site will be automatically subscribed to the Simplenews
208 newsletter whose ID number is entered. Structure your entries like this:
209 <strong>
210 <p>newsletterID|comments<br /></p>
211 For example:
212 <br>63|Subscribe all new users to Brix Realty Inc</br>
213 </strong>
214 <p>Only one newsletter ID can be entered.</p>'),
215 );
216 $form['option settings']['views_mail_subscribe_group_newsletter'] = array(
217 '#type' => 'textarea',
218 '#title' => t('Groups whose new users are autosubscribed to newsletters'),
219 '#default_value' => variable_get('views_mail_subscribe_group_newsletter', ''),
220 '#cols' => 80,
221 '#rows' => 10,
222 '#description' => t('Specify here the node IDs of groups whose new members you wish to be subscribed to Simplenews
223 newsletters. You enter the group ID number, followed by a | character followed by the newsletter ID number to use for
224 subscriptions followed by another | and whatever comments you have for this groupID|newsletterID pair.
225 Structure your entries like this:
226 <strong>
227 <p>groupID|newsletterID|comments<br /></p>
228 For example:
229 <br>12|63|Beverly Hills subscibe to Brix Realty Inc</br>
230 <br>13|64|Encino Terrace subscribe to Mail Views</br>
231 </strong>
232 <p>Each groupID|newsletterID pair must be on a separate separated by a linefeed.</p>'),
233 );
234
235 $form['settings'] = array(
236 '#type' => 'fieldset',
237 '#title' => t('Test Settings'),
238 '#weight' => -10,
239 );
240 $form['settings']['views_mail_email_test_mode'] = array(
241 '#type' => 'checkbox',
242 '#title' => t('Email test mode'),
243 '#default_value' => variable_get('views_mail_email_test_mode', 1),
244 '#description' => t('When test mode is on, emails will not actually be sent to recipients. Uncheck this option when ready to start sending actual emails.')
245 );
246 $form['settings']['views_mail_email_test_send'] = array(
247 '#type' => 'select',
248 '#title' => t('Email test handling'),
249 '#default_value' => variable_get('views_mail_email_test_send', 0),
250 '#options' => array(
251 0 => t('Display to sender, do not send'),
252 1 => t('Send to test email address instead of recipient address'),
253 ),
254 );
255 $form['settings']['views_mail_email_test_address'] = array(
256 '#type' => 'textfield',
257 '#title' => t('Email test address'),
258 '#default_value' => variable_get('views_mail_email_test_address', variable_get('site_mail', '')),
259 );
260
261
262 return system_settings_form($form);
263 }
264
265 function views_mail_fields($view, $reset = FALSE) {
266 static $options;
267 if ($reset || empty($options)) {
268 $options = array();
269 }
270 if ($reset || empty($options[$view->vid])) {
271 $options = array();
272 $options[$view->vid]['name']['author_name'] = t('Node author name');
273 $options[$view->vid]['mail']['author_mail'] = t('Node author email');
274 $fields = _views_get_fields();
275 foreach ($view->field as $key => $field) {
276 if ($fields[$field['fullname']]['content_field']['type'] == 'nodereference') {
277 $nlabel = t('Nodereference author name: ');
278 $mlabel = t('Nodereference author mail: ');
279 }
280 elseif ($fields[$field['fullname']]['content_field']['type'] == 'userreference') {
281 $nlabel = t('Userreference name: ');
282 $mlabel = t('Userreference mail: ');
283 }
284 else {
285 $nlabel = t('Field value: ');
286 $mlabel = t('Field value: ');
287 }
288 $options[$view->vid]['name'][$field['queryname']] = $nlabel ._views_mail_get_label($field['queryname'], $field['label']);
289 $options[$view->vid]['mail'][$field['queryname']] = $mlabel . _views_mail_get_label($field['queryname'], $field['label']);
290 }
291 }
292 return $options[$view->vid];
293 }
294
295 /**
296 * The Views Mail form displayed in views_pre_view().
297 *
298 * @param objec $view
299 * @param array $items
300 * @param array $form_values
301 * @return array $form
302 */
303 function views_mail_mail_form($view, $items, $form_values = NULL) {
304 if (isset($form_values) && ($form_values['op'] != t('Cancel') || $form_values['op'] != t('Return'))) {
305 $step = intval($form_values['step'] + 1);
306 }
307 else {
308 $step = 1;
309 }
310 $form['#multistep'] = TRUE;
311 $form['#redirect'] = FALSE;
312
313 // May need to alter this value if the multistep form gets stuck and won't go past a step.
314 $form['#skip_duplicate_check'] = TRUE;
315
316 $_SESSION['views_mail']['step'] = $step;
317 switch ($step) {
318 case 1:
319 // CREATE MESSAGE
320 $form['step'] = array('#type' => 'hidden', '#value' => $step);
321 $hidden = array('from', 'from_name');
322 $comment = t('Send a message using information from the view below. Select the fields that represent the recipient name and email address and type in the subject and message.');
323 $form['#theme'] = 'views_mail_form';
324 $substitutions = views_mail_get_substitutions($view);
325 $form_values['substitutions'] = serialize($substitutions);
326 $form['substitutions'] = array('#type' => 'hidden', '#value' => $form_values['substitutions']);
327 $form += views_mail_message_form($view, $form_values, $comment, $hidden);
328 $form['group']['submit'] = array('#type' => 'submit', '#value' => t('Send'));
329 return $form;
330
331 case 2:
332 // CONFIRM LIST
333
334 $form['step'] = array('#type' => 'hidden', '#value' => $step);
335 $form['#theme'] = 'views_mail_form';
336 $comment .= t('OK to send to %number recipients?', array('%number' => number_format(sizeof($_SESSION['views_mail']['recipients']))));
337 if ($form_values['update']) $comment .= t(' <em>Note: This list will be updated when sent, and the number of recipients may change.</em>');
338 $comment = '<p>'. $comment .'</p>';
339
340 // Show the form again, but display the values instead of allowing them to be input.
341 $hidden = array('subject', 'newsletter', 'message', 'number', 'unit', 'from', 'from_name', 'to_name', 'to_mail', 'distinct');
342 $form += views_mail_message_form($view, $form_values, $comment, $hidden);
343 $form['group']['#collapsible'] = FALSE;
344 $form['group']['confirm'][] = array('#type' => 'submit', '#value' => t('Confirm'));
345 $form['group']['confirm'][] = array('#type' => 'submit', '#value' => t('Cancel'));
346 $form['#suffix'] = theme('views_mail_recipients_list', $_SESSION['views_mail']['recipients']);
347 return $form;
348
349 case 3:
350 // SEND MAIL
351 // unset the view items so they don't display on this screen and show results instead.
352 $form['submit'] = array('#type' => 'submit', '#value' => t('Return'));
353 return $form;
354 }
355 }
356
357 /**
358 * Multistep form submit handler.
359 * Do things that must only be done once in this step.
360 * Actions in the multistep form itself will end up getting triggered more than once.
361 */
362 function views_mail_mail_form_submit($form_id, $form_values) {
363 // Store the form values in a variable so they can be accessed by views_query_alter().
364 $view = $GLOBALS['current_view'];
365 switch ($form_values['step']) {
366 case 1:
367 views_mail_warning();
368 $form_values['substitute'] = $form_values['update'] ? FALSE : (strstr($form_values['message'], '%') ? TRUE : FALSE);
369 $form_values['distinct'] = isset($form_values['distinct']) ? intval($form_values['distinct']) : 1;
370 // Store the form values in a variable so they can be accessed by views_query_alter().
371 variable_set('views_mail_form_values_'.$view->vid, $form_values);
372 // Rerun the query to get the recipient name and email fields.
373 $items = views_build_view('items', $view, $view->args, $view->use_pager, $view->limit, $view->page, $view->offset, $view->filters);
374 views_mail_get_recipients($form_values, $view, $items['items']);
375 break;
376 case 2:
377 views_mail_warning();
378 if ($form_values['op'] != t('Return') && $form_values['op'] != t('Cancel')) {
379 // TODO check if using scheduled mail and create an action item instead of mailing immediately.
380 $view = $GLOBALS['current_view'];
381 $recipients = $_SESSION['views_mail']['recipients'];
382 return _views_mail_send_mail($form_values, $recipients, $view);
383 }
384 break;
385 }
386 }
387
388 /**
389 * Prepare a message input form.
390 *
391 * @param $form_values - the form values array for this form.
392 * @param $comment - the description for the form fieldset.
393 * @param $hidden - an array of elements that should be displayed instead of input,
394 * values are added as hidden values and displayed to user, used when form values are confirmed.
395 */
396 function views_mail_message_form($view, $form_values, $comment, $hidden = array()) {
397 $user = $GLOBALS['user'];
398 $substitutions = (array) unserialize($form_values['substitutions']);
399 $form['group'] = array(
400 '#type' => 'fieldset',
401 '#title' => t('Send Mail'),
402 '#collapsible' => TRUE,
403 '#collapsed' => !empty($form_values['subject']) ? FALSE : TRUE,
404 '#description' => $comment,
405 );
406 $options = views_mail_fields($view);
407 if (in_array('to_name', $hidden)) {
408 $form['message'] = array('#type' => 'hidden', '#value' => $form_values['to_name']);
409 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'to_name', $form_values['to_name']));
410 } else{
411 $form['group']['to_name'] = array(
412 '#type' => 'select',
413 '#title' => t('Recipient name'),
414 '#default_value' => !empty($form_values['to_name']) ? $form_values['to_name'] : 'author_name',
415 '#options' => $options['name'],
416 '#multiple' => FALSE,
417 //'#required' => TRUE,
418 );
419 }
420 if (in_array('to_mail', $hidden)) {
421 $form['message'] = array('#type' => 'hidden', '#value' => $form_values['to_mail']);
422 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'to_mail', $form_values['to_mail']));
423 } else{
424 $form['group']['to_mail'] = array(
425 '#type' => 'select',
426 '#title' => t('Recipient email'),
427 '#default_value' => !empty($form_values['to_mail']) ? $form_values['to_mail'] : 'author_mail',
428 '#options' => $options['mail'],
429 '#multiple' => FALSE,
430 //'#required' => TRUE,
431 );
432 }
433
434 if ($hidden) $form['group']['display'][] = array('#type' => 'markup', '#value' => '<dl>');
435
436 $from_name = !empty($form_values['from_name']) ? $form_values['from_name'] : $user->name;
437 $from_mail = !empty($form_values['from']) ? $form_values['from'] : $user->mail;
438
439 if (in_array('from_name', $hidden)) {
440 $form['from_name'] = array('#type' => 'hidden', '#value' => $from_name);
441 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'from_name', $form_values['from_name']));
442 } else{
443 $form['group']['from_name'] = array(
444 '#type' => 'textfield',
445 '#title' => t('From name'),
446 '#default_value' => $from_name,
447 '#maxlength' => '50',
448 '#required' => TRUE,
449 );
450 }
451
452 if (in_array('from', $hidden)) {
453 $form['from'] = array('#type' => 'hidden', '#value' => $from_mail);
454 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'from', $form_values['from']));
455 } else{
456 $form['group']['from'] = array(
457 '#type' => 'textfield',
458 '#title' => t('From address'),
459 '#default_value' => $from_mail,
460 '#maxlength' => '50',
461 '#required' => TRUE,
462 );
463 }
464
465 if (in_array('subject', $hidden)) {
466 $form['subject'] = array('#type' => 'hidden', '#value' => $form_values['subject']);
467 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'subject', $form_values['subject']));
468 } else{
469 $form['group']['subject'] = array(
470 '#type' => 'textfield',
471 '#title' => t('Subject'),
472 '#default_value' => $form_values['subject'],
473 '#maxlength' => '130',
474 '#required' => TRUE,
475 );
476 }
477 if (in_array('newsletter', $hidden)) {
478 $form['newsletter'] = array('#type' => 'hidden', '#value' => $form_values['newsletter']);
479 $display = views_mail_get_node_field($form_values['newsletter'], 'title') . " (" . $form_values['newsletter'] . ")";
480 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'newsletter', $display));
481 } else{
482 $form['group']['newsletter'] = array(
483 '#type' => 'select',
484 '#title' => t('Newsletter to send to this group'),
485 '#default_value' => $form_values['newsletter'],
486 '#options' => views_mail_newsletters(),
487 '#description' => t('The newsletter that contains the message to be sent.'),
488 '#required' => TRUE,
489 );
490 }
491
492 if (in_array('message', $hidden)) {
493 $form_values['message'] = views_mail_get_node_field($form_values['newsletter'], 'body');
494 $form['message'] = array('#type' => 'hidden', '#value' => $form_values['message']);
495 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'message', $form_values['message']));
496 } else{
497 $form['group']['message'] = array(
498 '#type' => 'hidden',
499 '#value' => views_mail_get_node_field($form_values['newsletter'], 'body'),
500 );
501 //
502 // No need for message box in form
503 //
504 // $form['group']['message'] = array(
505 // '#type' => 'textarea',
506 // '#title' => t('Message'),
507 // '#default_value' => views_mail_get_node_field($form_values['newsletter'], 'body'),
508 // '#rows' => '0',
509 // '#required' => FALSE,
510 // '#description' => t('The message that should be sent. This should come from the newsletter selected.'),
511 // );
512 }
513
514 if (in_array('distinct', $hidden)) {
515 $form['message'] = array('#type' => 'hidden', '#value' => $form_values['distinct']);
516 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'distinct', $form_values['distinct']));
517 } else{
518 $form['group']['distinct'] = array(
519 '#type' => 'select',
520 '#title' => t('Distinct'),
521 '#default_value' => isset($form_values['distinct']) ? $form_values['distinct'] : 1,
522 '#options' => array(1 => t('Yes'), 0 => t('No')),
523 '#multiple' => FALSE,
524 '#description' => t('Send only to distinct email addresses? If Yes, only one message will be sent to any one recipient. Set to No if you are customizing the message with information from selected records to be sure a different message is sent for each one.'),
525 );
526 }
527
528 if (in_array('number', $hidden)) {
529 $form['number'] = array('#type' => 'hidden', '#value' => $form_values['number']);
530 $form['unit'] = array('#type' => 'hidden', '#value' => $form_values['unit']);
531 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'number', $form_values['number']));
532 $form['group']['display'][] = array('#type' => 'markup', '#value' => theme('views_mail_form_display', 'unit', $form_values['unit']));
533 } else{
534 $form['group']['schedule'] = array(
535 '#type' => 'fieldset',
536 '#title' => t('Schedule'),
537 '#collapsible' => TRUE,
538 '#collapsed' => TRUE,
539 '#description' => t('Set time period to wait before sending this message.'),
540 );
541
542 $form['group']['schedule']['number'] = array(
543 '#type' => 'textfield',
544 '#title' => t('Number'),
545 '#required' => true,
546 '#size' => 3,
547 '#default_value' => $form_values['number'] ? $form_values['number'] : 0,
548 );
549
550 $form['group']['schedule']['unit'] = array(
551 '#type' => 'select',
552 '#title' => t('Unit'),
553 '#options' => array(
554 '1' => 'seconds',
555 '60' => 'minutes',
556 '3600' => 'hours',
557 '86400' => 'days',
558 'weekdays' => 'weekdays'
559 ),
560 '#default_value' => $form_values['unit'] ? $form_values['unit'] : 86400,
561 );
562 }
563
564 $form['group']['vid'] = array(
565 '#type' => 'hidden',
566 '#value' => $view->vid,
567 );
568
569 return $form;
570 }
571
572 /**
573 * Display a warning to the user if email is still in test mode.
574 *
575 */
576 function views_mail_warning() {
577 // Warn if we are still in test mode.
578 $test = variable_get('views_mail_email_test_mode', 1);
579 $test_send = variable_get('views_mail_email_test_send', 0);
580 if ($test) {
581 if (!$test_send) {
582 $message = t('mail will be displayed and not sent.');
583 }
584 else {
585 $message = t('mail will be sent to test email address @address.', array('@address' => variable_get('views_mail_email_test_address', variable_get('site_mail', ''))));
586 }
587 drupal_set_message(t('Views Mail test mode is on.') . $message . t('Turn test mode off at !link', array(
588 '!link' => l('admin/settings/views_mail', base_path() . 'admin/settings/views_mail'))
589 ), 'error');
590 }
591 }
592
593 /**
594 * Global substitution array
595 */
596 function _views_mail_global_subs($node = NULL, $recipient = NULL) {
597 $variables = array(
598 '%site_name' => variable_get('site_name', ''),
599 '%recipient_name' => $recipient['name'],
600 '%recipient_mail' => $recipient['mail'],
601 '%node_nid' => $node ? $node->nid : 0,
602 '%node_uid' => $node ? $node->uid : 0,
603 '%node_url' => $node ? url('node/' . $node->nid, NULL, NULL, TRUE) : '',
604 '%node_type' => $node ? $node->type : '',
605 '%node_title' => $node ? $node->title : '',
606 '%node_teaser' => $node ? node_view($node, true, false, false) : '',
607 '%node_body' => $node ? node_view($node, false, false, false) : '',
608 );
609 return $variables;
610 }
611
612 function _views_mail_get_label($field, $label) {
613 return ($label ? str_replace(' ', '', $label) : $field);
614 }
615
616 function views_mail_get_substitutions($view) {
617 $substitutions = array();
618 foreach ($view->field as $field) {
619 $substitutions['%'. ($field['label'] ? str_replace(' ', '', $field['label']) : $field['queryname'])] = $field['queryname'];
620 }
621 $node = new StdClass();
622 $node->nid = 0;
623 $substitutions += _views_mail_global_subs($node, $recipient);
624 return $substitutions;
625 }
626
627 /**
628 * Create a recipient list from the filtered view.
629 *
630 * TODO - is it best to store it in a SESSION or add it to the form_values?
631 * it could be a long list, so assuming the SESSION option is better.
632 */
633 function views_mail_get_recipients($form_values, $view, $items) {
634 if (empty($items)) {
635 return;
636 }
637
638 $substitutions = unserialize($form_values['substitutions']);
639 $substitute = $form_values['substitute'] ? $form_values['substitute'] : TRUE;
640 $message = $form_values['message'] ? $form_values['message'] : '';
641 $distinct = isset($form_values['distinct']) ? $form_values['distinct'] : 1;
642
643 $recipients = array();
644 $used_mails = array();
645
646 // iterate through each row of the query results
647 foreach ($items as $row_no => $row) {
648 // reset variables
649 $list = array();
650 $invalid = false;
651 if (!empty($row->to_name) && !empty($row->to_mail) && !in_array($row->to_mail, $used_mails)) {
652 $list['name'] = $row->to_name;
653 $list['mail'] = $row->to_mail;
654 if ($distinct) $used_mails[] = $row->to_mail;
655 }
656 else {
657 $invalid = TRUE;
658 }
659
660 // if the message needs substitutions based on current record, make them now
661 if ($substitute && !$invalid) {
662 $replace = array();
663 foreach ($substitutions as $from => $to) {
664 if (isset($to)) {
665 if (isset($row->$to)) {
666 $replace[$from] = $row->$to;
667 }
668 }
669 }
670 // Customize the message for this recipient.
671 if (!$node) $node = node_load($row->nid);
672 $replace = $replace + _views_mail_global_subs($node, $list);
673 $list['message'] = strtr($message, $replace);
674 }
675
676 // duplicate mail addresses will be combined
677 // invalid and empty values will be dropped
678 if (!$invalid && $distinct && $list['name'] && $list['mail']) {
679 $recipients[$list['mail']] = $list;
680 }
681 elseif (!$invalid && !$distinct && $list['name'] && $list['mail']) {
682 $recipients[] = $list;
683 }
684
685 unset($list);
686 }
687 $_SESSION['views_mail']['recipients'] = $recipients;
688 return $recipients;
689 }
690
691 /**
692 * Alter query to add to_name and to_mail fields to the view based on selected preferences.
693 * This is where we need to get $form_values from a SESSION variable since this is
694 * not called from within the form.
695 */
696 function _views_mail_query_alter(&$query, $view, $summary, $level) {
697 $form_values = variable_get('views_mail_form_values_'.$view->vid, array());
698
699 $to_name = $form_values['to_name'];
700 $to_mail = $form_values['to_mail'];
701 $distinct = $form_values['distinct'];
702
703 if (empty($to_name) || empty($to_mail)) {
704 return;
705 }
706 $set_to_name = FALSE;
707 $set_to_mail = FALSE;
708
709 if ($to_name == 'author_name') {
710 $query->ensure_table('users', true);
711 $query->add_field('name', 'users', 'to_name');
712 $set_to_name = TRUE;
713 }
714 if ($to_mail == 'author_mail') {
715 $query->ensure_table('users', true);
716 $query->add_field('mail', 'users', 'to_mail');
717 $set_to_mail = TRUE;
718 }
719 if (!$set_to_mail || !$set_to_name) {
720 $fields = _views_get_fields();
721 // iterate through each field in this view
722 foreach ($view->field as $field_name => $field) {
723 if ($field['queryname'] == $to_name) {
724 $to_name_view_field = $field['fullname'];
725 }
726 if ($field['queryname'] == $to_mail) {
727 $to_mail_view_field = $field['fullname'];
728 }
729 /*
730 * TODO - This is not working right yet.
731 * Need to get userreference and nodereference fields added into the query properly
732 // Special case for userreference field, get user info.
733 if ($fields[$to_name_view_field]['content_field']['type'] == 'userreference') {
734 $query->add_table('node_userreference', false, 1, array('left' => array('table' => 'user', 'field' => 'uid'), 'right' => array('field' => 'uid')));
735 $query->add_field('name', 'node_userreference', 'to_name');
736 $set_to_name = TRUE;
737 }
738 if ($fields[$to_mail_view_field]['content_field']['type'] == 'userreference') {
739 $query->add_table('node_userreference', false, 1, array('left' => array('table' => 'user', 'field' => 'uid'), 'right' => array('field' => 'uid')));
740 $query->add_field('mail', 'node_userreference', 'to_mail');
741 $set_to_mail = TRUE;
742 }
743 // Special case for nodereference field, get referenced node's user info.
744 if ($fields[$to_name_view_field]['content_field']['type'] == 'nodereference') {
745 $query->add_table('node_nodereference', false, 1, array('left' => array('table' => 'node', 'field' => 'nid'), 'right' => array('field' => $field_name)));
746 $query->add_table('nodereference_user', false, 1, array('left' => array('table' => 'user', 'field' => 'uid'), 'right' => array('field' => 'uid')));
747 $query->add_field('name', 'nodereference_user', 'to_name');
748 $set_to_name = TRUE;
749 }
750 if ($fields[$to_mail_view_field]['content_field']['type'] == 'nodereference') {
751 $query->add_table('node_nodereference', false, 1, array('left' => array('table' => 'node', 'field' => 'nid'), 'right' => array('field' => $field_name)));
752 $query->add_table('nodereference_user', false, 1, array('left' => array('table' => 'user', 'field' => 'uid'), 'right' => array('field' => 'uid')));
753 $query->add_field('mail', 'nodereference_user', 'to_mail');
754 $set_to_mail = TRUE;
755 }
756 */
757 }
758 }
759 // If none of those items were the to name or to mail,
760 // just use the value of the selected field.
761 if (!$set_to_mail) {
762 $parts = explode('.', $to_mail_view_field);
763 $query->add_field($parts[1], $parts[0], 'to_mail');
764 }
765 if (!$set_to_name) {
766 $parts = explode('.', $to_name_view_field);
767 $query->add_field($parts[1], $parts[0], 'to_name');
768 }
769 }
770
771 /**
772 * Mailer function
773 *
774 * Pass email through this function to allow a way to run tests without actually sending mail
775 * If $test is set to TRUE, progress will be displayed on screen
776 * If $test_send is set to TRUE email will actually be sent to test email account instead of recipient
777 *
778 */
779 function _views_mail_send_mail($form_values, $recipients, $view) {
780 $site_name = variable_get('site_name', '');
781 $log_type = $form_values['log_type'] ? $form_values['log_type'] : 'watchdog';
782 $test = variable_get('views_mail_email_test_mode', 1);
783 $test_send = variable_get('views_mail_email_test_send', 0);
784 $test_mail = variable_get('views_mail_email_test_mail', variable_get('site_mail', $sender['mail']));
785 if ($test) $log_type = 'screen';
786
787 if (empty($recipients)) {
788 _views_mail_error_log($log_type, t('No recipients were provided.'));
789 return;
790 }
791
792 $subject = $site_name ? '['. $site_name .'] ' : '';
793 $subject .= $form_values['subject'] ? $form_values['subject'] : '';
794 $nid = $form_values['newsletter'] ? $form_values['newsletter'] : '';
795 $message = views_mail_get_node_field($nid, 'body') ? views_mail_get_node_field($nid, 'body') : '';
796 $from = $form_values['from'] ? $form_values['from'] : variable_get('site_mail', '');
797 $from_name = $form_values['from_name'] ? $form_values['from_name'] : $site_name;
798 $sender = theme('views_mail_email', $from, $from_name);
799 $number = $form_values['number'] ? $form_values['number'] : 0;
800 $unit = $form_values['unit'] ? $form_values['unit'] : 86400;
801
802 if (!$from) {
803 _views_mail_error_log($log_type, t('No from address was provided.'));
804 return;
805 } elseif (!$subject) {
806 _views_mail_error_log($log_type, t('No subject was provided.'));
807 return;
808 } elseif (!$message) {
809 _views_mail_error_log($log_type, t('No message was provided.'));
810 return;
811 }
812
813 $results = array();
814 foreach ((array) $recipients as $to => $rec) {
815 $logged = false;
816 $hit = "0";
817
818 if ($rec['mail']) {
819
820 // Get opt-out parameters;
821
822 $accept_mail = 'y';
823 $ooresult = db_query("SELECT uid FROM {users} where mail = '" . $rec['mail'] . "'");
824 while ($oouid = db_fetch_object($ooresult)) {
825 $account = user_load(array('uid' => $oouid->uid, 'status' => 1));
826 if (!$account->views_mail_accept) {
827 $accept_mail = 'n';
828 }
829 }
830
831 $hit .= "|A";
832 $recipient = theme('views_mail_email', $rec['mail'], $rec['name']);
833
834
835 if ($accept_mail == 'y') {
836
837 // use customized message, if provided, otherwise regular message
838 $this_message = ($rec['message']) ? $rec['message'] : $message;
839
840 // Use key, if provided, otherwise create one.
841 $key = 'views_mail:'. $view->name .':'. $rec['key'] ? $rec['key'] : $rec['mail'];
842
843 if (!$test || $test === FALSE) {
844
845 $hit .= "|B";
846
847 if ($number > 0) {
848
849 // Send mail later
850 // This is how I save the send e-mail request as an action
851
852 $params = array();
853 $params['from'] = $from; // from address
854 $params['recipient'] = $recipient; // recipient address
855 $params['subject'] = $subject; // message subject
856 $params['message'] = $message; // message
857
858 $function = 'action_views_mail_send'; // the action function
859 $type = 'Email'; // the type of action
860 $desc = 'Views mail action for ' . $recipient;
861
862 // Create the action
863 // No need for watchdog entry because it is done automatically by actions_save using $desc.
864
865 $aid = actions_save($function, $type, $params, $desc); // This will give me an $aid to use below:
866
867 // Values I need to send in order to process a sched_act_asa
868 // This is the $edit array I prepare
869
870 $edit = array();
871
872 $edit['which'] = $aid; // This is the aid (action ID)
873 $edit['a1type'] = 9; // Choose 9 just because. Don't know how sched_act works, but it doesn't go up to 9 now.
874 $edit['a2type'] = 0;
875 $edit['a3type'] = 0;
876 $edit['a4type'] = 0;
877 $edit['terms'] = array();
878 $edit['number'] = $number; // quantity of time
879 $edit['unit'] = $unit; // seconds
880
881 // This is the scheduling action function
882
883 action_sched_act_asa('do', $edit);
884
885 $results[] = array(t('Success'), $rec['name'], check_plain($recipient));
886 $logged = true;
887
888 } else { // $number if else
889
890 // Send mail now
891
892 if ($result = mimemail($sender, $recipient, $subject, $message)) {
893 $hit .= "|1";
894 _views_mail_error_log($log_type, t('Sent mail to %name (%mail)', array(
895 '%name' => $rec['name'], '%mail' => $rec['mail'], '%rec_message' => $rec['message'], '%message' => $message)));
896 _views_mail_log($sender, $recipient, $subject, $message);
897 $results[] = array(t('Success'), $rec['name'], check_plain($recipient));
898 $logged = true;
899 }
900
901 } // end $number if
902
903 } else { // if test else
904
905 if ($test_mail && $test_send) {
906 $hit .= "|2";
907 if ($result = mimemail($sender, $test_mail, $subject, $message)) {
908 $hit .= "|3";
909 _views_mail_error_log($log_type, t('Sent test to %test_mail for %mail.', array(
910 '%test_mail' => $test_mail, '%name' => $rec['name'], '%mail' => $rec['mail'])));
911 $results[] = array(t('Success'), $rec['name'], check_plain($recipient));
912 $logged = true;
913 } else {
914 $hit .= "|4";
915 _views_mail_error_log($log_type, t('Failure sending test to %test_mail for %mail).', array(
916 '%test_mail' => $test_mail, '%mail' => $recipient)));
917 $logged = true;
918 $results[] = array(t('Failure!'), $rec['name'], check_plain($recipient));
919 } // end if
920
921 } else { // test_mail if
922 $hit .= "|5";
923 _views_mail_error_log($log_type, t('Test mode! No mail sent to %test_mail for %mail.', array(
924 '%test_mail' => $test_mail, '%name' => $rec['name'], '%mail' => $rec['mail'])) );
925 $logged = true;
926 $results[] = array(t('Success'), $rec['name'], check_plain($recipient));
927 } // end test mail if
928
929 } // end test if
930
931 if (!$logged) {
932 $hit .= "|6";
933 _views_mail_error_log($log_type, t('Failure sending mail to %mail (Result: %reason) (Test: %test) (Sender: %sender) (Subject: %subject) (Hit: %hit)', array(
934 '%mail' => $recipient, '%reason' => $result, '%test' => $test, '%sender' => $sender, '%subject' => $subject, '%message' => $message, '%hit' => $hit)));
935 }
936
937 } // end $accept_mail if
938
939
940 } elseif ($rec['name']) { // rec mail elseif
941 _views_mail_error_log($log_type, t('Missing email address for %name (%mail) (%hit)', array('%name' => $rec['name'], '%mail' => $recipients, '%hit' => $hit)));
942 $logged = true;
943 $results[] = array(t('Failure!'), $rec['name'], check_plain($recipient));
944 }
945
946
947 } // end $rec['mail'] if
948
949 return theme('views_mail_mail_results', $results);
950 }
951
952 function theme_views_mail_mail_results($results) {
953 return t('<h3>Results:</h3>') . theme('table', array(t('Result'), t('Recipient'), t('Email')) , $results);
954 }
955
956 /**
957 * Log messages about email progress
958 */
959 function _views_mail_error_log($type, $message) {
960 switch ($type) {
961 case ('screen'):
962 drupal_set_message($message, 'error');
963 break;
964 case ('both'):
965 drupal_set_message($message, 'error');
966 watchdog('views_mail', $message);
967 break;
968 default:
969 watchdog('views_mail', $message);
970 break;
971 }
972 }
973
974 /**
975 * Log mail results
976 */
977 function _views_mail_log($sender, $recipient, $subject, $message) {
978 // TODO
979 // Create a database record of this transaction.
980 }
981
982 /**
983 * theme for displaying hidden form values
984 */
985 function theme_views_mail_form_display($name, $value) {
986 switch ($name) {
987 case ('subject'):
988 $label = t('Subject');
989 break;
990 case ('newsletter'):
991 $label = t('Newsletter');
992 break;
993 case ('message'):
994 $label = t('Message');
995 break;
996 case ('from_name'):
997 $label = t('From');
998 break;
999 case ('number'):
1000 $label = t('Send after time period of:');
1001 $value = ($value);
1002 break;
1003 case ('unit'):
1004 $label = '';
1005 switch($value) {
1006 case (1):
1007 $value = t('Seconds.');
1008 break;
1009 case (60):
1010 $value = t('Minutes.');
1011 break;
1012 case (3600):
1013 $value = t('Hours.');
1014 break;
1015 case (86400):
1016 $value = t('Days.');
1017 break;
1018 case (weekdays):
1019 $value = t('Weekdays.');
1020 break;
1021 }
1022 break;
1023 case ('to_mail'):
1024 $label = t('Recipient email');
1025 break;
1026 case ('to_name'):
1027 $label = t('Recipient name');
1028 break;
1029 case ('distinct'):
1030 $label = t('Distinct message');
1031 break;
1032
1033 }
1034 if (!empty($label) && !empty($value)) {
1035 $output = '<dt><label>'. $label .':</label></dt>' ;
1036 }
1037 if (!empty($value)) {
1038 $output .= '<dd>'. $value .'</dd>';
1039 }