/[drupal]/contributions/modules/connect/connect_actions.php
ViewVC logotype

Contents of /contributions/modules/connect/connect_actions.php

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


Revision 1.9 - (show annotations) (download) (as text)
Wed Apr 8 15:11:51 2009 UTC (7 months, 2 weeks ago) by stevem
Branch: MAIN
CVS Tags: DRUPAL-5--2-0-BETA1, HEAD
Changes since 1.8: +15 -4 lines
File MIME type: text/x-php
move CC settings to admin from participant node
1 <?php
2 // $Id: connect_actions.php,v 1.8 2009/04/08 14:52:20 stevem Exp $
3
4 /*
5 * action functions make themselves known and take effect when called as hooks from connect
6 *
7 * @params $op
8 * 'describe' -> return array of info for config UI
9 * 'requires' -> describe parent & child data requirements for config UI
10 * 'menu' -> return array of cached menu items, used to register callbacks
11 * 'validate' -> evaluate child content (NB $child = (array) $form_data, not (obj) $child)
12 * 'form_alter' -> allows actions to affect the child node form when before it's displayed
13 * 'insert' -> handle changes to $target nodes
14 * 'update' -> handle changes to $target nodes
15 * 'delete' -> handle changes to $target nodes
16 * 'display' -> node is being displayed
17 * 'status' -> reports on status of child node interaction
18 * 'redirect' -> sets a destination instead of the form again on successful submit
19 * 'admin-validate' -> function settings are being validated
20 * ($parent->nid contains the parent id, and $parent->data holds the form values)
21 *
22 * @return
23 * if $op='display', an array('data' => string)
24 * if $op='status', an array('message' => string, 'show_form' => boolean)
25 * if $op='validate', array('status' => boolean, 'message' => string)
26 * if $op='form_alter', object $child = the revised form fields
27 */
28
29
30 /**
31 * Mandatory action, handles basic housekeeping
32 */
33 function connect_action_basic(&$parent, &$child, $op='', $target='parent') {
34 if ($target == 'child') {
35 switch ($op) {
36 case 'insert' :
37 // create parent-child mapping
38 $sql = "INSERT INTO {connect_data} (nid,pid) VALUES (%d,%d);";
39 db_query($sql, $child->nid, $parent->nid);
40
41 // record fact of current user's participation
42 $_SESSION['connect_action_basic_'.$parent->nid] = TRUE;
43 $_SESSION['connect_action_thanks_'.$parent->nid] = TRUE;
44 break;
45
46 case 'delete' :
47 // delete parent-child mapping
48 $sql = "DELETE FROM {connect_data} WHERE nid=%d;";
49 db_query($sql, $child->nid);
50 break;
51 }
52 }
53 elseif ($target == 'parent') {
54 switch ($op) {
55 case 'describe' :
56 $return = array();
57 $return['title'] = 'Basic settings';
58 return $return;
59 break;
60
61 case 'requires' :
62 $return = array();
63 $default = connect_node_options($parent->nid, 'is_live');
64 $default = $default ? $default : 'no';
65 $return['variables']['is_live'] = array(
66 '#type' => 'radios',
67 '#title' => t('Is this campaign ready to go live?'),
68 '#description' => t('This is only relevant if you are sending faxes and emails. \'No\' means that no emails, faxes, etc. will be sent; you will instead see a display of the message(s) that would have been sent.'),
69 '#options' => array('yes' => 'Yes', 'no' => 'No'),
70 '#default_value' => $default,
71 '#required' => TRUE,
72 );
73
74 $types = connect_participant_types_options();
75 $types[0] = '';
76 asort($types);
77 $return['variables']['participant_type'] = array(
78 '#type' => 'select',
79 '#title' => 'Participant node type',
80 '#options' => $types,
81 '#default_value' => connect_node_options($parent->nid, 'participant_type'),
82 '#required' => TRUE,
83 );
84
85 $return['variables']['participant_title'] = array(
86 '#type' => 'textfield',
87 '#title' => 'Title for the participants',
88 '#default_value' => connect_node_options($parent->nid, 'participant_title'),
89 '#required' => TRUE,
90 );
91
92 $return['variables']['call_to_action'] = array(
93 '#type' => 'textfield',
94 '#title' => 'Call to action',
95 '#default_value' => connect_node_options($parent->nid, 'call_to_action'),
96 '#required' => TRUE,
97 );
98
99 $return['variables']['thankyou'] = array(
100 '#type' => 'textarea',
101 '#size' => 4,
102 '#title' => 'Thank-you message',
103 '#default_value' => connect_node_options($parent->nid, 'thankyou'),
104 '#required' => TRUE,
105 );
106
107 return $return;
108 break;
109
110 case 'status' :
111 // display 'thank you' message
112 if (isset($_SESSION['connect_action_thanks_'.$parent->nid])) {
113 unset($_SESSION['connect_action_thanks_'.$parent->nid]);
114 $message = connect_node_options($parent->nid, 'thankyou');
115 return array(
116 'status' => $message,
117 'show_form' => FALSE,
118 );
119 }
120 }
121 }
122 }
123
124
125 /**
126 * Set a custom redirect page post-connect-form-submission
127 */
128 function connect_action_redirect_submit(&$parent, &$child, $op='', $target='parent') {
129 switch($op) {
130 case 'describe' :
131 $return = array();
132 $return['title'] = 'Redirect on submit';
133 $return['desc'] = 'Allows you to specify a URL or node to present on successful form submission.';
134 return $return;
135 break;
136
137 case 'requires' :
138 $return = array();
139 $return['variables'] = array(
140 'redirect_submit_target' => array(
141 '#type' => 'textfield',
142 '#size' => 20,
143 '#title' => 'Target page',
144 '#default_value' => connect_node_options($parent->nid, 'redirect_submit_target'),
145 '#required' => TRUE,
146 ),
147 );
148 return $return;
149 break;
150
151 case 'redirect' :
152 $return = connect_node_options($parent->nid, 'redirect_submit_target');
153 return $return;
154 break;
155 }
156 }
157
158 /**
159 * provide a signing block in addition to or instead of the regular form
160 * - blocks are declared to Drupal in connect.module
161 * - see connect_blocks.php for block generation code
162 */
163 /*
164 function connect_action_provide_block(&$parent, &$child, $op='', $target='parent') {
165 switch($op) {
166 case 'describe' :
167 $return = array();
168 $return['title'] = 'Provide a block';
169 $return['desc'] = 'Makes the participation form available as a Drupal block.';
170 return $return;
171 break;
172
173 case 'requires' :
174 $return = array();
175 $visibility = connect_node_options($parent->nid, 'provide_block_visibility');
176 $visibility = empty($visibility) ? 0 : $visibility;
177
178 $return['variables'] = array(
179 'provide_block_text' => array(
180 '#type' => 'textfield',
181 '#size' => 20,
182 '#title' => 'Text for link to main node',
183 '#description' => 'If blank, no link to the main node will appear in the block',
184 '#default_value' => connect_node_options($parent->nid, 'provide_block_text'),
185 '#required' => FALSE,
186 ),
187 'provide_block_noform' => array(
188 '#type' => 'checkbox',
189 '#title' => 'Prevent display of main form',
190 '#default_value' => connect_node_options($parent->nid, 'provide_block_noform'),
191 '#required' => TRUE,
192 ),
193 'provide_block_visibility' => array(
194 '#type' => 'radios',
195 '#title' => 'Block visibility',
196 '#options' => array(
197 'use regular block configuration',
198 'only display on this page',
199 'display everywhere except this page',
200 ),
201 '#default_value' => $visibility,
202 '#required' => TRUE,
203 ),
204 );
205 return $return;
206 break;
207
208 case 'status' :
209 if (connect_node_options($parent->nid, 'provide_block_noform')) {
210 return array(
211 'show_form' => FALSE,
212 );
213 }
214 }
215 }
216 */
217
218
219
220 /**
221 * Adds a CSS-based display to the parent node showing how many of the target number of participants have participated
222 */
223 function connect_action_display_progress(&$parent, &$child, $op='', $target='parent') {
224 switch($op) {
225 case 'describe' :
226 $return = array();
227 $return['title'] = 'Display progress bar';
228 $return['desc'] = 'Adds a CSS-based display showing how many of the target number have participated.';
229 return $return;
230 break;
231
232 case 'requires' :
233 $return = array();
234 $return['variables'] = array(
235 'display_progress_goal' => array(
236 '#type' => 'textfield',
237 '#size' => 20,
238 '#title' => 'Target no. of participants',
239 '#default_value' => connect_node_options($parent->nid, 'display_progress_goal'),
240 '#required' => TRUE,
241 ),
242 );
243 return $return;
244 break;
245
246 case 'display' :
247 if ($target != 'parent' || $parent == NULL) {
248 return;
249 }
250
251 $done = connect_participant_count($parent);
252 $title = connect_node_options($parent->nid, 'participant_title');
253 $goal = connect_node_options($parent->nid, 'display_progress_goal');
254 if ($goal > 0) {
255 $pct = round($done/$goal, 2) * 100;
256 $pct_display = $pct > 100 ? 100 : $pct;
257 } else {
258 $goal = 0;
259 $pct = 0;
260 $pct_display = 0;
261 }
262 $return['data'] = theme('connect_display_progress', $goal, $pct, $pct_display, $title);
263 return $return;
264 break;
265 }
266 }
267
268 function theme_connect_display_progress($goal, $pct, $pct_display, $title) {
269 $progress_bar = <<<EOT
270 <div>
271 <div id="connect-progress-report">$goal $title</div>
272 <div id="connect-progress-border">
273 <div id="connect-progress-bar" style="width: $pct_display%;">
274 $pct%
275 </div>
276 </div>
277 </div>
278 EOT;
279 return $progress_bar;
280 }
281
282
283 /**
284 * Enforces a one person, one vote policy based on a unique identifier
285 */
286 function connect_action_voteonce(&$parent, &$child, $op='', $target='child') {
287
288 $message = connect_node_options($parent->nid, 'voteonce_message');
289 $message = $message ? $message : t('You have already participated.');
290
291 switch($op) {
292 case 'describe' :
293 $return = array();
294 $return['title'] = 'One vote per person';
295 $return['desc'] = 'Prevent the same person from participating more than once.';
296 return $return;
297 break;
298
299 case 'requires' :
300 $return = array();
301 $return['child'] = array(
302 'voteonce_identifier' => 'Unique identifier (i.e., full name, membership #, or email address)',
303 );
304 $return['variables'] = array(
305 'voteonce_message' => array(
306 '#type' => 'textfield',
307 '#title' => 'Message to display when someone attempts to participate more than once',
308 '#default_value' => $message,
309 '#required' => TRUE,
310 ),
311 );
312 return $return;
313 break;
314
315 case 'validate' :
316 // don't check for this when editing an existing child node
317 if (isset($child->status) && $child->status == 0) {
318 return;
319 }
320
321 $map = connect_get_map($parent->nid);
322 $test_value = connect_value('voteonce_identifier', $parent, $child, 'child');
323 $fieldname = $map['voteonce_identifier'];
324 $field_keys = connect_get_field_keys($fieldname);
325 $test_db = _connect_get_cck_db_info($fieldname);
326 $test_table = $test_db['table'];
327 $test_column = $test_db['columns'][$field_keys[0]]['column'];
328
329 $sql = "SELECT count(*) FROM {".$test_table."} t, {connect_data} p WHERE t.nid=p.nid AND t.$test_column = '%s' AND p.pid = %d";
330 $count = db_result(db_query($sql, array($test_value, $parent->nid)));
331 $already_voted = ($count != 0);
332
333 if ($already_voted) {
334 form_set_error('', t($message));
335 }
336 break;
337
338 case 'status' :
339 // if this user has already participated
340 if (isset($_SESSION['connect_action_basic_'.$parent->nid])) {
341 return array(
342 'status' => $message,
343 'show_form' => FALSE,
344 );
345 }
346 break;
347 }
348 }
349
350
351 /**
352 * provide a list of participants
353 */
354 function connect_action_display_participants(&$parent, &$child, $op='', $target='child') {
355 switch($op) {
356 case 'describe' :
357 $return = array();
358 $return['title'] = 'Display participants';
359 $return['desc'] = 'Select fields to display in a public listing of participants. (Double opt-in enabled.)';
360 return $return;
361
362 case 'requires' :
363 $return = array();
364 $return['variables'] = array(
365 'display_participants_pager' => array(
366 '#type' => 'textfield',
367 '#title' => 'How many participants would you like to display at a time?',
368 '#default_value' => connect_node_options($parent->nid, 'display_participants_pager') ? connect_node_options($parent->nid, 'display_participants_pager') : 25,
369 '#required' => TRUE,
370 ),
371 );
372 $return['child'] = array(
373 'display_participants_displayme' => 'Display my name in public lists',
374 );
375
376 // does this action use double opt-in?
377 $double_opt_in = connect_value('double_optin_token', $parent, $child, 'child');
378 if ($double_opt_in) {
379 $return['child']['double_optin_token'] = 'Double opt-in confirmation field';
380 }
381
382 // select child fields to display
383 $idx = 0;
384 $child_type = connect_node_options($parent->nid, 'participant_type');
385 $cck_options = _connect_get_child_fields($child_type);
386 $map = connect_get_map($parent->nid);
387 if (!empty($cck_options[$map['display_participants_displayme']])) {
388 unset($cck_options[$map['display_participants_displayme']]);
389
390 if (!empty($cck_options)) {
391 $return['variables']['display_participants_fields_intro'] = array(
392 '#value' => 'Select the items to display, in order.',
393 );
394 foreach ($cck_options as $name=>$title) {
395 if (empty($name)) {
396 continue;
397 }
398 $return['variables']['display_participants_fields_' . $idx] = array(
399 '#type' => 'select',
400 '#title' => '',
401 '#options' => $cck_options,
402 '#default_value' => connect_node_options($parent->nid, 'display_participants_fields_' . $idx),
403 '#required' => FALSE,
404 );
405 // need at least one!
406 if ($idx == 0) {
407 $return['variables']['display_participants_fields_' . $idx]['#required'] = TRUE;
408 $return['variables']['display_participants_fields_' . $idx]['#title'] = 'participant info';
409 }
410 $idx++;
411 }
412 }
413 }
414 return $return;
415
416 case 'menu' :
417 $return = array(
418 array(
419 'path' => 'connect/participants',
420 'title' => 'Display participants',
421 'callback' => '_connect_action_display_participants',
422 'type' => MENU_CALLBACK,
423 'access' => TRUE,
424 ),
425 );
426 return $return;
427 break;
428
429 case 'display' :
430 if ($target != 'parent' || $parent == NULL) {
431 return;
432 }
433 $return['data'] = theme('connect_action_display_participants', $parent->nid);
434 return $return;
435 break;
436 }
437 }
438
439 /* themeable function */
440 function theme_connect_action_display_participants($parent_id) {
441 $link = l(t('Display '). connect_node_options($parent_id, 'participant_title'), 'connect/participants/'. $parent_id);
442 return "<div id='connect-display-participants'>$link</div>";
443 }
444
445
446 /**
447 * allows participant-generated content to replace the parent content
448 */
449 function connect_action_content_replace(&$parent, &$child, $op='', $target='child') {
450 switch($op) {
451 case 'describe' :
452 $return = array();
453 $return['title'] = 'Content: rewrite';
454 $return['desc'] = 'Allows participants to revise the content provided by the parent node.';
455 return $return;
456
457 case 'requires' :
458 $return = array();
459 $return['parent'] = array(
460 'data_replace_parent' => 'Content replace: the content that can be rewritten.',
461 );
462 $return['child'] = array(
463 'data_replace_child' => 'Content replace: the participant\'s version.',
464 );
465 return $return;
466
467 case 'form_alter':
468 $map = connect_get_map($parent->nid);
469 $field = $map['data_replace_child'];
470 $key = connect_get_field_keys($field);
471 $child[$field][0][$key[0]]['#default_value'] = connect_value('data_replace_parent', $parent, $child, 'parent');
472 return $child;
473 break;
474
475 case 'insert' :
476 if ($target == 'child') {
477 $addition = connect_value('data_replace_child', $parent, $child, 'child');
478 connect_value('data_replace_parent', $parent, $child, 'parent', $addition);
479 }
480 break;
481 }
482 }
483
484
485 /**
486 * allows participant-generated content to be added to the parent content
487 */
488 function connect_action_content_append(&$parent, &$child, $op = '', $target = 'child') {
489 switch($op) {
490 case 'describe' :
491 $return = array();
492 $return['title'] = 'Content: append';
493 $return['desc'] = 'Allows participants to add their own comments, etc. to the content provided by the parent node.';
494 return $return;
495
496 case 'requires' :
497 $return = array();
498 $return['parent'] = array(
499 'data_append_parent' => 'Content append: the content that can be added on to.',
500 );
501 $return['child'] = array(
502 'data_append_child' => 'Content append: the participant\'s addition.',
503 );
504 return $return;
505
506 case 'insert' :
507 if ($target == 'child') {
508 $original = connect_value('data_append_parent', $parent, $child, 'parent');
509 $addition = connect_value('data_append_child', $parent, $child, 'child');
510 connect_value('data_append_parent', $parent, $child, 'parent', "$original\n$addition");
511 }
512 break;
513 }
514 }
515
516
517
518 /* Allow form to be embedded in another site */
519 /*
520 function connect_action_embed(&$parent, &$child, $op = '', $target = 'child') {
521 switch ($op) {
522 case 'describe' :
523 $return = array();
524 $return['title'] = 'Make Embeddable';
525 $return['desc'] = 'Makes petition form embeddable in external site';
526 return $return;
527 break;
528 //case 'menu' :
529 //$items = array();
530 //$items[] = array(
531 //'path' => 'connect/embed',
532 //'title' => 'Connect Embed',
533 //'callback' => '_connect_embed',
534 //'type' => MENU_CALLBACK,
535 //'access' => TRUE,
536 //);
537 //return $items;
538 //break;
539 //case 'form_alter' : //loop through and reduce the length of textfields
540 //foreach ()
541 //$child[$field][0][$key[0]]['#default_value'] = connect_value('data_replace_parent', $parent, $child, 'parent');
542 //return $child;
543 }
544 }
545
546 function _connect_embed($nid = NULL) {
547 if (!is_numeric(arg(2)) || !arg(2)) {
548 print '<p>Please specify a parent ID</p>';
549 return;
550 }
551 $parent_node = node_load($nid);
552 if (!isset($parent_node)) {
553 print '<p>Invalid ID</p>';
554 return;
555 }
556 if (!connect_is_parent_node($parent_node)){
557 print '<p>Referenced node is not a parent type</p>';
558 return;
559 }
560 $parent_node =& _connect_parent_node($parent_node);
561
562 // require a CAPTCHA on the form?
563 //if (!_connect_captcha_test('connect_form_block')) {
564 //return $return;
565 //}
566
567
568 $form = drupal_get_form('connect_form_block');
569 //$link = empty($text) ? '' : '<p>&raquo;&nbsp;'. l($text, "node/$nid") .'</p>';
570 print '<h2>' . $parent_node->title . '</h2>' . $parent_node->body . $form;
571 }
572 */
573
574
575 /**
576 * send email
577 */
578 function connect_action_send_email(&$parent, &$child, $op = '', $target = 'child') {
579 $mail_op_list = array('to', 'cc', 'bcc');
580
581 switch($op) {
582 case 'describe' :
583 $return = array();
584 $return['title'] = 'Send email';
585 $return['desc'] = 'Sends email to/cc/bcc addresses that you specify or that can be looked up on the basis of participant information.';
586 $return['cache'] = TRUE;
587 return $return;
588 break;
589
590 case 'requires' :
591 require_once(drupal_get_path('module','connect') . '/connect_lookup.php');
592 $return = array();
593
594 // stringent validation?
595 $return['variables']['email_stringent'] = array(
596 '#type' => 'radios',
597 '#title' => 'Use stringent email address validation?',
598 '#description' => 'This requires that email addresses point to an existing, fully-qualified domain name.',
599 '#options' => array('yes' => 'Yes', 'no' => 'No'),
600 '#default_value' => connect_node_options($parent->nid, 'email_stringent'),
601 '#required' => TRUE,
602 );
603
604 // CC the participant?
605 $return['variables']['email_cc_participant'] = array(
606 '#type' => 'radios',
607 '#title' => 'CC the participant?',
608 '#description' => 'Should emails generated by the campaign also be CCed to the participant?',
609 '#options' => array('yes' => 'Yes', 'no' => 'No'),
610 '#default_value' => connect_node_options($parent->nid, 'email_cc_participant'),
611 '#required' => TRUE,
612 );
613
614 // re-sending batch size
615 $batch = connect_node_options($parent->nid, 'email_batch');
616 $batch = $batch ? $batch : 0;
617 $return['variables']['email_batch'] = array(
618 '#type' => 'textfield',
619 '#title' => 'Batch size for re-sending failed emails',
620 '#description' => 'How many failed emails should be re-tried in one session? Set to zero to process an unlimited number of emails.',
621 '#default_value' => $batch,
622 '#required' => TRUE,
623 );
624
625 // send HTML mail?
626 if (module_exists('mimemail')) {
627 if (!variable_get('mimemail_alter', 0)) {
628 $return['variables']['email_send_html'] = array(
629 '#type' => 'radios',
630 '#title' => 'Send HTML email using the mimemail module?',
631 '#options' => array('yes' => 'Yes', 'no' => 'No'),
632 '#default_value' => connect_node_options($parent->nid, 'email_send_html'),
633 '#required' => TRUE,
634 );
635 }
636 } else {
637 $return['variables']['email_send_html'] = array(
638 '#value' => '<p><strong>Send HTML Email</strong><br />' . t('If you want to be able to send HTML emails, install the mimemail module.') . '</p>',
639 );
640 }
641
642 // TO/CC salutation
643 $return['variables']['email_salutation'] = array(
644 '#type' => 'radios',
645 '#title' => 'Prefix a list of the recipients\' names?',
646 '#description' => 'Connect can automatically add a list of the TO and CC target names above the message.',
647 '#options' => array('yes' => 'Yes', 'no' => 'No'),
648 '#default_value' => connect_node_options($parent->nid, 'email_salutation'),
649 '#required' => TRUE,
650 );
651
652 // defined target
653 $return['variables']['email_defined_targets'] = array (
654 '#type' => 'textarea',
655 '#title' => 'Email targets',
656 '#description' => 'Enter your targets one to a line, using the format "to,email@example.com,person name". You can specify "to" or "cc" or "bcc" in the first field. There must be at least one "to" address (between the defined targets and lookup target). The name element is used as the salutation at the top of the email.',
657 '#default_value' => connect_node_options($parent->nid, 'email_defined_targets'),
658 '#required' => FALSE,
659 );
660
661 // target lookup
662 $lookup_types = connect_get_lookup_types(TRUE);
663 $lookup_actions = array('' => '');
664 foreach ($mail_op_list as $action) {
665 $lookup_actions[$action] = $action;
666 }
667
668 $return['variables']['email_lookup'] = array(
669 '#type' => 'fieldset',
670 '#title' => 'Target lookup',
671 );
672 $return['variables']['email_lookup']['email_lookup_intro'] = array(
673 '#value' => '<p>You may define one target address that will be determined on the basis of information provided by the participants (such as an elected representative corresponding to a postal code).</p>',
674 );
675 $return['variables']['email_lookup']['email_lookup_action'] = array(
676 '#type' => 'select',
677 '#title' => 'Email action',
678 '#options' => $lookup_actions,
679 '#default_value' => connect_node_options($parent->nid, 'email_lookup_action'),
680 '#required' => FALSE
681 );
682 $return['variables']['email_lookup']['email_lookup_type'] = array(
683 '#type' => 'select',
684 '#title' => 'Type of lookup',
685 '#options' => $lookup_types,
686 '#default_value' => connect_node_options($parent->nid, 'email_lookup_type'),
687 '#required' => FALSE,
688 );
689
690 // participant signature
691 $child_type = connect_node_options($parent->nid, 'participant_type');
692 $child_fields = _connect_get_child_fields($child_type);
693 $return['variables']['email_signature'] = array(
694 '#type' => 'fieldset',
695 '#title' => 'Signature',
696 );
697 $return['variables']['email_signature']['email_signature_intro'] = array(
698 '#value' => '<p>Select the participant fields that will be appended to the message as a signature</p>',
699 );
700 for ($row = 1; $row <= 3; $row++) {
701 $return['variables']['email_signature']["email_signature_{$row}"] = array(
702 '#type' => 'fieldset',
703 '#title' => "Row $row",
704 );
705 for ($col = 1; $col <= 2; $col++) {
706 $return['variables']['email_signature']["email_signature_{$row}"]["email_signature_{$row}_{$col}"] = array(
707 '#type' => 'select',
708 '#title' => '',
709 '#options' => $child_fields,
710 '#default_value' => connect_node_options($parent->nid, "email_signature_{$row}_{$col}"),
711 '#required' => FALSE,
712 );
713 }
714 }
715
716 $return['parent'] = array(
717 'email_subject' => 'Send email: the subject line of the email',
718 'email_body' => 'Send email: the body of the email',
719 );
720 $return['child'] = array(
721 'email_from' => 'Participant\'s email address',
722 'email_defined_result' => 'Send email: record the e-mail success/failure message',
723 //'email_cc_me' => 'Send email: should the email be CCed to the participant?',
724 );
725
726 // add requirements from lookup type, if set
727 $lookup = connect_target_lookup($parent, $child, 'requires', 'email');
728 if (is_array($lookup)) {
729 foreach(array('variables','parent','child') as $key) {
730 if (isset($lookup[$key])) {
731 foreach($lookup[$key] as $newkey=>$add) {
732 if ($key == 'variables') {
733 $return[$key]['email_lookup'][$newkey] = $add;
734 }
735 else {
736 $return[$key][$newkey] = $add;
737 }
738 }
739 }
740 }
741 }
742
743 return $return;
744 break;
745
746 /*
747 case 'menu' :
748 $return = array(
749 array(
750 'path' => 'connect/email_resend',
751 'title' => 'Re-send email',
752 'callback' => '_connect_action_send_email_resend_failed',
753 'type' => MENU_CALLBACK,
754 'access' => TRUE,
755 ),
756 );
757 return $return;
758 break;
759 */
760
761 case 'menu' :
762 break;
763
764 case 'admin-validate' :
765 $stringent = (connect_node_options($parent->nid, 'email_stringent') == 'yes');
766 $targets = _connect_parse_email_targets($parent->data['campaign_variables']['variables_connect_action_email_defined']['email_defined_targets']);
767 $processed = array();
768 $count = 0;
769
770 // check defined targets
771 foreach ($targets as $target) {
772 // type of email activity
773 if (!in_array($target['type'], $mail_op_list)) {
774 form_set_error('email_defined_targets_'. $count++, 'Email targets: "'. htmlentities($target['type']) . '" must be one of ' . implode(', ', $mail_op_list));
775 }
776
777 // address correctness
778 if (($stringent && !_connect_valid_email_strict($target['email'])) ||
779 (!$stringent && !valid_email_address($target['email']))) {
780 form_set_error('email_defined_targets_'. $count++, 'Email targets: "'. htmlentities($target['email']) .'" is not a valid email address');
781 }
782 elseif (in_array($target['email'], $processed)) {
783 form_set_error('email_defined_targets_'. $count++, 'Email targets: "'. htmlentities($target['email']) .'" should not appear more than once in the list');
784 }
785 else {
786 $processed[] =$target['email'];
787 }
788 }
789 break;
790
791 case 'validate' :
792 if ($target != 'child') {
793 return;
794 }
795 $stringent = (connect_node_options($parent->nid, 'email_stringent') == 'yes');
796 $email = connect_value('email_from', $parent, $child, 'child');
797 if (($stringent && !_connect_valid_email_strict($email)) || (!$stringent && !valid_email_address($email))) {
798 form_set_error('', 'Please enter a valid email address');
799 }
800 // call validation from lookup type
801 $lookup_type = connect_node_options($parent->nid, 'email_lookup_type');
802 if ($lookup_type) {
803 connect_target_lookup($parent, $child, 'validate', 'email');
804 }
805 break;
806
807 case 'insert' :
808 if ($target != 'child') {
809 return;
810 }
811 $active = (connect_node_options($parent->nid, 'is_live') == 'yes');
812 $html = (connect_node_options($parent->nid, 'email_send_html') == 'yes');
813 $addresses = array();
814 $headers = array();
815 $salutation = array();
816
817 // entities for adding elements to html or plaintext emails
818 $br = $html ? "<br />\r\n\r\n" : "\r\n\r\n";
819 $p_on = $html ? '<p>' : '';
820 $p_off = $html ? "</p>\r\n\r\n" : "\r\n\r\n";
821
822 // direct targets
823 $targets = _connect_parse_email_targets(connect_node_options($parent->nid, 'email_defined_targets'));
824 foreach ($targets as $target) {
825 if (!empty($target['email']) && in_array($target['type'], $mail_op_list)) {
826 eval('$addresses[' . $target['type'] . '][] = $target[\'email\'];');
827 $salutation[$target['type']][] = $target['name'];
828 }
829 }
830
831 // lookup target
832 require_once(drupal_get_path('module','connect') . '/connect_lookup.php');
833 $target = connect_target_lookup($parent, $child, 'lookup', 'email');
834 $target['type'] = connect_node_options($parent->nid, 'email_lookup_action');
835 if (!empty($target['email']) && in_array($target['type'], $mail_op_list)) {
836 eval('$addresses[' . $target['type'] . '][] = $target[\'email\'];');
837 $salutation[$target['type']][] = $target['name'];
838 }
839
840 // set salutation string
841 $salute = '';
842 if (connect_node_options($parent->nid, 'email_salutation') == 'yes') {
843 $salute = $p_on . 'TO: ' . implode(', ', $salutation['to']) . $p_off;
844 if (!empty($salutation['cc'])) {
845 $salute .= $p_on . 'CC: ' . implode(', ', $salutation['cc']) . $p_off;
846 }
847 }
848
849 // set signature
850 $signature = '';
851 for ($row = 1; $row <= 3; $row++) {
852 $line = '';
853 for ($col = 1; $col <= 2; $col++) {
854 $field = connect_node_options($parent->nid, "email_signature_{$row}_{$col}");
855 if ($field) {
856 $path = _connect_get_field_path($child, $field);
857 eval('$temp = $child'. $path .';');
858 if ($temp) {
859 $line .= check_plain($temp) . ' ';
860 }
861 }
862 }
863 if ($line) {
864 $signature .= "$line$br";
865 }
866 }
867 $signature = $signature ? "\r\n\r\n$p_on$signature$p_off" : '';
868
869 // do we cc the participant?
870 //if (_connect_positive_value(connect_value('email_cc_me', $parent, $child, 'child'))) {
871 if (_connect_positive_value(connect_node_options($parent->nid, 'email_cc_participant'))) {
872 $addresses['cc'][] = connect_value('email_from', $parent, $child, 'child');
873 }
874
875 // basic message elements
876 $message->to = implode(', ', $addresses['to']);
877 $message->from = connect_value('email_from', $parent, $child, 'child');
878 $message->subject = connect_value('email_subject', $parent, $child, 'parent');
879 $message->body = $salute . connect_value('email_body', $parent, $child, 'parent') . $signature;
880
881 // add CC, BCC headers
882 if (!empty($addresses['cc'])) {
883 $headers['CC'] = implode(', ', $addresses['cc']);
884 }
885 if (!empty($addresses['bcc'])) {
886 $headers['BCC'] = implode(', ', $addresses['bcc']);
887 }
888 $message->headers = $headers;
889
890 // send it
891 $result = _connect_send_email($message, $html, $active);
892
893 // save result
894 $_SESSION['connect_'.$parent->nid.'_email_sent'] = $result ? implode(', ', $salutation['to']) : FALSE;
895 $result = $result ? "Success" : "Failed";
896 connect_value('email_defined_result', $parent, $child, 'child', $result);
897 node_save($child);
898 break;
899
900 case 'status' :
901 $message = '';
902 if (isset($_SESSION['connect_'.$parent->nid.'_email_sent'])) {
903 $message = $_SESSION['connect_'.$parent->nid.'_email_sent'] ? 'Your email message was sent to: ' .$_SESSION['connect_'.$parent->nid.'_email_sent'] : 'Sorry, but there was a problem sending the message. The problem will be investigated, and your message will be sent when the problem is resolved.';
904 unset($_SESSION['connect_'.$parent->nid.'_email_sent']);
905 }
906 return array(
907 'status' => $message
908 );
909 break;
910 }
911 }
912
913 /*
914 function _connect_action_send_email_resend_failed_page(){
915 drupal_set_title('Re-send failed e-mails');
916
917 $output = "<p>This utility allows you to re-send messages for any failed e-mail deliveries.</p>";
918 $output .= "";
919
920 return $output;
921 }
922 */
923
924 /**
925 * utility to re-send mail from participants with failed results
926 **/
927 function _connect_action_send_email_resend_failed() {
928 $p_nid = arg(1);
929 $parent = node_load($p_nid);
930 if (!$parent || !connect_is_parent_node($parent)) return;
931
932 $batch = (int) connect_node_options($parent->nid, 'email_batch');
933 $done = 0;
934
935 $report_header = array('participant email', 'result');
936 $report_data = array();
937
938 $sql = "SELECT nid FROM {connect_data} WHERE pid = %d";
939 $result = db_query($sql, $p_nid);
940 while ($row = db_fetch_object($result)) {
941 $child = node_load($row->nid);
942 if (connect_value('email_defined_result', $parent, $child, 'child') == "Failed") {
943 //set lock to prevent connect_nodeapi from firing;
944 $_SESSION['connect_child_lock_insert'] = TRUE;
945 connect_call_hooks($parent, $child, 'insert');
946 unset($_SESSION['connect_child_lock_insert']);
947 $report_data[] = array(
948 l(connect_value('email_from', $parent, $child, 'child'), 'node/' . $child->nid),
949 connect_value('email_defined_result', $parent, $child, 'child')
950 );
951 $done ++;
952 if ($batch && $done >= $batch) break;
953 }
954 }
955
956 if (empty($report_data)) {
957 $output .= "<p>There were no failed emails to re-send.</p>\n";
958 }
959 else {
960 $output = "<p>$done emails were re-sent</p>\n";
961 $output .= theme_table($report_header, $report_data);
962 }
963 return $output;
964 }
965
966
967 /**
968 * Sends fax (using the myfax.com service) to a specific name and fax no. defined in the parent node.
969 */
970 function connect_action_myfax_defined(&$parent, &$child, $op='', $target='child') {
971 switch($op) {
972 case 'describe' :
973 $return = array();
974 $return['title'] = 'MyFax (defined target)';
975 $return['desc'] = 'Sends fax (using the myfax.com service) to a specified name and fax no.';
976 return $return;
977 break;
978
979 case 'requires' :
980 $return = array();
981 $return['variables'] = array(
982 'fax_to_number' => array (
983 '#type' => 'textfield',
984 '#size' => 20,
985 '#title' => 'Target fax no.',
986 '#default_value' => connect_node_options($parent->nid, 'fax_to_number'),
987 '#required' => TRUE,
988 ),
989 'fax_to_name' => array (
990 '#type' => 'textfield',
991 '#size' => 20,
992 '#title' => 'Target name',
993 '#default_value' => connect_node_options($parent->nid, 'fax_to_name'),
994 '#required' => TRUE,
995 ),
996 'myfax_email' => array(
997 '#type' => 'textfield',
998 '#title' => 'MyFax account \'from\' email address',
999 '#default_value' => connect_node_options($parent->nid, 'myfax_email'),
1000 '#required' => TRUE,
1001 ),
1002 'myfax_password' => array(
1003 '#type' => 'textfield',
1004 '#title' => 'MyFax password',
1005 '#default_value' => connect_node_options($parent->nid, 'myfax_password'),
1006 ),
1007 );
1008 $return['parent'] = array(
1009 'fax_subject' => 'Fax subject',
1010 'fax_body' => 'Fax body',
1011 );
1012 $return['child'] = array(
1013 'fax_direct_result' => 'MyFax (direct) success/failure message',
1014 'fax_from' => 'Fax \'from\' name',
1015 );
1016 return $return;
1017 break;
1018
1019 case 'validate' :
1020 if ($target != 'child') {
1021 return;
1022 }
1023 $name = connect_value('fax_from', $parent, $child, 'child');
1024 if (empty($name)) {
1025 form_set_error('', 'Please enter your name.');
1026 }
1027 break;
1028
1029 case 'insert' :
1030 if ($target != 'child') {
1031 return;
1032 }
1033
1034 $fax = array();
1035 $fax['from_mail'] = connect_node_options($parent->nid, 'myfax_email');
1036 $fax['to_fax'] = connect_node_options($parent->nid, 'fax_to_number');
1037 $fax['to_name'] = connect_node_options($parent->nid, 'fax_to_name');
1038 $fax['password'] = connect_node_options($parent->nid, 'myfax_password');
1039 $fax['body'] = connect_value('fax_body', $parent, $child, 'parent');
1040 $fax['subject'] = connect_value('fax_subject', $parent, $child, 'parent');
1041 $fax['from_name'] = connect_value('fax_from', $parent, $child, 'child');
1042
1043 $message = connect_myfax_prepare($fax);
1044 $active = (connect_node_options($parent->nid, 'is_live') == 'yes');
1045 $result = _connect_send_email($message, FALSE, $active);
1046
1047 // save result
1048 $_SESSION['connect_'.$parent->nid.'_direct_fax_sent'] = $result;
1049 $result = $result ? "Success" : "Failed";
1050 connect_value('fax_direct_result', $parent, $child, 'child', $result);
1051 node_save($child);
1052 break;
1053
1054 case 'status' :
1055 $message = '';
1056 if (isset($_SESSION['connect_'.$parent->nid.'_direct_fax_sent'])) {
1057 $message = $_SESSION['connect_'.$parent->nid.'_direct_fax_sent'] ? 'Your fax message was sent!' : 'Sorry, but there was a problem sending the message. The problem will be investigated, and your message will be sent when the problem is resolved.';
1058 unset($_SESSION['connect_'.$parent->nid.'_direct_fax_sent']);
1059 }
1060 return array(
1061 'status' => $message
1062 );
1063 break;
1064 break;
1065 }
1066 }
1067
1068 /**
1069 * Sends fax (using the myfax.com service) to a target determined by the participant\'s information.
1070 */
1071 function connect_action_myfax_lookup(&$parent, &$child, $op='', $target='child') {
1072 switch($op) {
1073 case 'describe' :
1074 $return = array();
1075 $return['title'] = 'MyFax (target lookup)';
1076 $return['desc'] = 'Sends fax (using the myfax.com service) to a target determined by the participant\'s information.';
1077 return $return;
1078 break;
1079
1080 case 'requires' :
1081 require_once(drupal_get_path('module','connect') . '/connect_lookup.php');
1082 $return = array();
1083 $options = connect_get_lookup_types(TRUE);
1084 $base['variables'] = array(
1085 'myfax_lookup_type' => array(
1086 '#type' => 'select',
1087 '#title' => 'MyFax target lookup',
1088 '#options' => $options,
1089 '#default_value' => connect_node_options($parent->nid, 'myfax_lookup_type'),
1090 '#required' => TRUE,
1091 ),
1092 'myfax_email' => array(
1093 '#type' => 'textfield',
1094 '#title' => 'MyFax account \'from\' email address',
1095 '#default_value' => connect_node_options($parent->nid, 'myfax_email'),
1096 '#required' => TRUE,
1097 ),
1098 'myfax_password' => array(
1099 '#type' => 'textfield',
1100 '#title' => 'MyFax password',
1101 '#default_value' => connect_node_options($parent->nid, 'myfax_password'),
1102 ),
1103 );
1104 $base['parent'] = array(
1105 'fax_subject' => 'Fax subject',
1106 'fax_body' => 'Fax body',
1107 );
1108 $base['child'] = array(
1109 'fax_lookup_result' => 'MyFax (lookup) success/failure message',
1110 'fax_from' => 'Fax \'from\' name',
1111 );
1112
1113 // add requirements from lookup type
1114 $lookup = connect_target_lookup($parent, $child, 'requires', 'myfax');
1115 if (is_array($lookup)) {
1116 foreach(array('variables','parent','child') as $key) {
1117 if (isset($lookup[$key])) {
1118 $return[$key] = $base[$key]+$lookup[$key];
1119 } else {
1120 $return[$key] = $base[$key];
1121 }
1122 }
1123 } else {
1124 $return = $base;
1125 drupal_set_message('You have not selected a lookup type. Please do so and then adjust any new settings that are required.');
1126 }
1127 return $return;
1128 break;
1129
1130 case 'validate' :
1131 if ($target != 'child') {
1132 return;
1133 }
1134 $name = connect_value('fax_from', $parent, $child, 'child');
1135 if (empty($name)) {
1136