Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
form_email.inc
1 <?php
18 require_once dirname(__FILE__).'/../form/form.inc';
19 require_once SQ_FUDGE_PATH.'/general/www.inc';
20 require_once SQ_FUDGE_PATH.'/general/file_system.inc';
21 require_once SQ_FUDGE_PATH.'/general/text.inc';
22 
34 class Form_Email extends Form
35 {
36 
37 
44  function Form_Email($assetid=0)
45  {
46  $this->Form($assetid);
47 
48  }//end constructor
49 
50 
61  function _getName($short_name=FALSE, $contextid=NULL)
62  {
63  // No context specified, using the current context
64  if ($contextid === NULL) {
65  $contextid = $GLOBALS['SQ_SYSTEM']->getContextId();
66  }//end if
67 
68  // Obtain the attribute value for Name from the specified Context
69  $values = $GLOBALS['SQ_SYSTEM']->am->getAttributeValuesByName('name', $this->type(), Array($this->id), $contextid);
70  if (empty($values) === TRUE) {
71  return parent::_getName($short_name, $contextid);
72  } else {
73  return $values[$this->id];
74  }
75 
76  }//end _getName()
77 
78 
89  function getFormHeader()
90  {
91  $header = parent::getFormHeader();
92 
93  $prefix = $this->getPrefix();
94 
95  // If we have a multi-page form, we would only need to know how we got
96  // here originally. Therefore, if we have been sent a referral URL from
97  // a previous page, use that instead.
98  // Otherwise, generate the referrer using what we have been sent by the
99  // HTTP request (with all the caveats that implies).
100  if (array_key_exists($prefix.'_referral_url', $_POST)) {
101  $referer = $_POST[$prefix.'_referral_url'];
102  } else {
103  $referer = (isset($_SERVER['HTTP_REFERER'])) ? $_SERVER['HTTP_REFERER'] : '';
104  }
105 
106  ob_start();
107  ?><input type="hidden" name="<?php echo $prefix; ?>_referral_url" value="<?php echo htmlentities($referer); ?>" /><?php
108  $header .= ob_get_clean();
109 
110  return $header;
111 
112  }//end getFormHeader()
113 
114 
123  function getFormInfo($html=FALSE)
124  {
125  $info = parent::getFormInfo();
126  $title = 'Form Information';
127  $information = ($html) ? '<b>'.$title.'</b><br />' : $title."\n\n";
128  $information .= ($html) ? '<table>' : '';
129 
130  foreach ($info as $name => $value) {
131  $information .= ($html) ? '<tr><td valign="top">'.ucwords(str_replace('_', ' ', $name)).'</td>' : ucwords(str_replace('_', ' ', $name)).' : ';
132  $information .= ($html) ? '<td valign="top">'.$value.'</td></tr>' : $value."\n";
133  }
134  // add form submission time
135  $now = date('d M Y g:i a', time());
136  $information .= ($html) ? '<tr><td valign="top">'.translate('cms_form_submission_time').'</td>' : translate('cms_form_submission_time').' : ';
137  $information .= ($html) ? '<td valign="top">'.$now.'</td></tr>' : $now."\n";
138  // add submission ip address
139  $ip_address = $_SERVER['REMOTE_ADDR'];
140  $information .= ($html) ? '<tr><td valign="top">'.translate('cms_form_submission_ip_address').'</td>' : translate('cms_form_submission_ip_address').' : ';
141  $information .= ($html) ? '<td valign="top">'.$ip_address.'</td></tr>' : $ip_address."\n";
142 
143  $information .= ($html) ? '</table>' : '';
144  return $information;
145 
146  }//end getFormInfo()
147 
148 
174  function cloneComponents(&$clone, $components, $override=FALSE)
175  {
176  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
177  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
178 
179  // Remove metadata schemas from form submission clone components
180  $metadata_schemas_key = array_search('metadata_schemas', $components);
181  if ($metadata_schemas_key !== FALSE) {
182  unset($components[$metadata_schemas_key]);
183  }
184 
185  if (!parent::cloneComponents($clone, $components, $override)) {
186  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
187  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
188  return FALSE;
189  }
190 
191  if (in_array('attributes', $components) || in_array('all', $components)) {
192  // send to a friend format
193  $recip = unserialize($this->attr('recipient_emails_format'));
194 
195  if(array_key_exists('to',$recip)) {
196  $recip = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $recip);
197  $recip['to'] = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $recip['to']);
198  } else {
199  $recip = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $recip);
200  }
201 
202  $rec = unserialize($this->attr('receipt_emails_format'));
203 
204  if (array_key_exists('to',$rec)) {
205  $rec = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $rec);
206  $rec['to'] = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $rec['to']);
207  } else {
208  $rec = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $rec);
209  }
210 
211  $staf = unserialize($this->attr('staf_format'));
212 
213  if (array_key_exists('to',$staf)) {
214  $staf = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $staf);
215  $staf['to'] = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $staf['to']);
216  } else {
217  $staf = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $staf);
218  }
219 
220  $sel = $this->attr('selective_emails');
221  foreach ($sel as $key => $null) {
222  $sel[$key]['address'] = str_replace('%response_'.$this->id.'_', '%response_'.$clone->id.'_', $sel[$key]['address']);
223  $sel[$key]['assetid'] = str_replace($this->id.':q', $clone->id.':q', $sel[$key]['assetid']);
224  }
225 
226  // field selections for STAF and receipt
227  $staf_field = str_replace($this->id.':q', $clone->id.':q', $this->attr('staf_field'));
228  $receipt_field = str_replace($this->id.':q', $clone->id.':q', $this->attr('receipt_field'));
229 
230  // save the information
231  $clone->setAttrValue('recipient_emails_format', serialize($recip));
232  $clone->setAttrValue('receipt_emails_format', serialize($rec));
233  $clone->setAttrValue('staf_format', serialize($staf));
234  $clone->setAttrValue('selective_emails', $sel);
235 
236  $clone->setAttrValue('staf_field', $staf_field);
237  $clone->setAttrValue('receipt_field', $receipt_field);
238 
239  $clone->saveAttributes();
240 
241  }//end if
242 
243  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
244  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
245  return TRUE;
246 
247  }//end cloneComponents()
248 
249 
258  function deleteQuestion(&$question)
259  {
260  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
261  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
262 
263  if (!parent::deleteQuestion($question)) {
264  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
265  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
266  return FALSE;
267  }
268 
269  if ($this->attr('staf_field') == $question->id) {
270  $this->setAttrValue('staf_field', '');
271  }
272 
273  if ($this->attr('receipt_field') == $question->id) {
274  $this->setAttrValue('receipt_field', '');
275  }
276 
277  if (!$this->saveAttributes()) {
278  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
279  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
280  return FALSE;
281  }
282 
283  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
284  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
285 
286  return TRUE;
287 
288  }//end deleteQuestion()
289 
290 
291 //-- POST-SUBMISSION ACTIONS --//
292 
293 
300  function finishForm()
301  {
302  // Perform submission actions which need to be executed before finish form
303  if (!$this->performSubmissionActions(TRUE)) {
304  // We had problems, print last page again
305  // Print the current page or the Confirmation Page if we're confirming things
306  $current_page = $this->getCurrentPageNumber();
307  $total_pages = $this->getTotalPages();
308 
309  if (($current_page == $total_pages) && $this->attr('use_confirmation_page')) {
310  echo $this->getConfirmationPageContents();
311  }
312  else {
313  $this->printPageContentsBodycopy();
314  }
315  return FALSE;
316  }
317 
318  parent::finishForm();
319  $this->mailRecipients();
320  $this->mailReceipt();
321  $this->sendToFriends();
322 
323  // Perform other submission actions that are active
324  $this->performSubmissionActions();
325 
326  // Perform selective actions
327  $this->runSelectiveEmails();
328 
329  return TRUE;
330 
331  }//end finishForm()
332 
333 
340  function mailReceipt()
341  {
342  $email_field_assetid = $this->attr('receipt_field');
343  if (empty($email_field_assetid)) return FALSE;
344 
345  $email_field = $GLOBALS['SQ_SYSTEM']->am->getAsset($email_field_assetid);
346  if (empty($email_field)) return FALSE;
347  $address = $email_field->getValue();
348 
349  $additional_reps = Array(
350  'receipt_address' => $address,
351  );
352 
353  $email_format_attr = $this->getAttribute('receipt_emails_format');
354 
355  // append the 'To:' address with the address from the e-mail field
356  $current_value = @unserialize($email_format_attr->value);
357  $current_value['to'][] = $address;
358  $email_format_attr->value = serialize($current_value);
359 
360  $this->sendEmail($email_format_attr, $additional_reps);
361 
362  return TRUE;
363 
364  }//end mailReceipt()
365 
366 
373  function mailRecipients()
374  {
375  $email_format_attr = $this->getAttribute('recipient_emails_format');
376  $this->sendEmail($email_format_attr);
377  return TRUE;
378 
379  }//end mailRecipients()
380 
381 
388  function _getAttachments()
389  {
390  $questions = $this->getAllQuestions();
391  $db = MatrixDAL::getDb();
392 
393  $file_assets = Array();
394  $filenames = Array();
395 
396  foreach ($questions as $q_assetid => $question) {
397  if ($question['question_type_code'] == 'form_question_type_file_upload') {
398  $q_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($q_assetid);
399  if (!is_null($q_asset) && $q_asset->attr('attach_to_mail')) {
400  $file_asset_id = $q_asset->getUploadedFileId();
401  if (!empty($file_asset_id)) {
402  $file_assets[] = $file_asset_id;
403  } else {
404  // We have a permanent storage
405  if (isset($q_asset->extra_data['filesystem_path']) && is_file($q_asset->extra_data['filesystem_path'])) {
406  $filenames[] = $q_asset->extra_data['filesystem_path'];
407  }
408  }
409  }
410  }
411  }
412 
413  return Array(
414  'assets' => $file_assets,
415  'filenames' => $filenames,
416  );
417 
418  }//end _getAttachments()
419 
420 
427  function sendToFriends()
428  {
429  $email_field_assetid = $this->attr('staf_field');
430  if (empty($email_field_assetid)) return FALSE;
431 
432  $email_field = $GLOBALS['SQ_SYSTEM']->am->getAsset($email_field_assetid);
433  if (empty($email_field)) return FALSE;
434  $addresses = preg_split('/[\s;,]+/',$email_field->getValue());
435 
436  $email_format_attr = $this->getAttribute('staf_format');
437 
438  // append the 'To:' address with the address from the e-mail field
439  $current_value = @unserialize($email_format_attr->value);
440  $current_value['to'] = array_merge($current_value['to'], $addresses);
441  $email_format_attr->value = serialize($current_value);
442 
443  $this->sendEmail($email_format_attr);
444 
445  return TRUE;
446 
447  }//end sendToFriends()
448 
449 
457  {
458  // attribute which holds all the selective email rules
459  $selective_emails = $this->attr('selective_emails');
460 
461  // these are where we store the recipients of each respective type of email...
462  // if rules pass then this will contain who is receiving each email
463  $recipients = Array();
464  $receipts = Array();
465  $stafs = Array();
466 
467  for (reset($selective_emails); NULL !== ($k = key($selective_emails)); next($selective_emails)) {
468  $sel_email =& $selective_emails[$k];
469 
470  // check to see whether it is valid in the first place
471  $valid = TRUE;
472 
473  if (empty($sel_email['rules'])) $valid = FALSE; // no rule parts!
474  if (empty($sel_email['send'])) $valid = FALSE; // type of mail is empty
475  if (empty($sel_email['address'])) $valid = FALSE; // address to send to is empty
476 
477  if ($valid) {
478 
479  // Short circuiting rules for this loop. If we are requiring ALL rule parts to succeed
480  // then we start with a Pass outcome and exit on the first Fail. If we are only needing
481  // ANY then we start with a Fail and exit on the first Pass.
482  $require_all = ($sel_email['require'] == 'all');
483  $passed = $require_all;
484 
485  // find the rule parts
486  $rule_parts =& $sel_email['rules'];
487 
488  for (reset($rule_parts); NULL !== ($rule_key = key($rule_parts)); next($rule_parts)) {
489  $rule =& $rule_parts[$rule_key];
490  $q_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($rule['assetid']);
491 
492  // if this rule is broken due to a deleted question, the rule
493  // will automatically fail
494  if (!$q_asset) {
495  $passed = FALSE;
496  break;
497  }
498 
499  $answer = $q_asset->getValue();
500 
501  $type_code = 'form_question_rule_type_'.$rule['name'];
502  $GLOBALS['SQ_SYSTEM']->am->includeAsset($type_code);
503  $rule_asset = new $type_code();
504  $rule_passed = $rule_asset->evaluate($answer, $rule, $q_asset);
505 
506  // Short Circuit evaluation, see note above this loop.
507  if ($require_all && !$rule_passed) {
508  // require ALL, rule part FAILED => fail whole rule
509  $passed = FALSE;
510  break;
511  } else if (!$require_all && $rule_passed) {
512  // require ANY, rule part PASSED => pass whole rule
513  $passed = TRUE;
514  break;
515  }
516 
517  }//end for rule parts
518 
519  if ($passed) {
520  // parse addresses into an array in case multiples are sent
521  $addresses = preg_split('/[\s;,]+/',$sel_email['address']);
522 
523  switch ($sel_email['send']) {
524  case 'recipient':
525  $recipients = array_merge($recipients, $addresses);
526  break;
527  case 'receipt':
528  $receipts = array_merge($receipts, $addresses);
529  break;
530  case 'staf':
531  $stafs = array_merge($stafs, $addresses);
532  break;
533  }
534  }
535 
536  }//end if valid
537 
538  }//end for selective email rules
539 
540 
541  // recipient emails
542  if (!empty($recipients)) {
543  // only send one of each type of email to each recipient
544  $recipients = array_unique($recipients);
545 
546  $email_format = $this->getAttribute('recipient_emails_format');
547 
548  // substitute generic keywords with email format-specific keywords
549  $current_value = @unserialize($email_format->value);
550 
551  if (!empty($current_value)) {
552  $current_value['to'] = $recipients;
553  $email_format->value = serialize($current_value);
554  $this->sendEmail($email_format);
555  }
556  }
557 
558 
559  // receipt emails
560  if (!empty($receipts)) {
561  // only send one of each type of email to each recipient
562  $receipts = array_unique($receipts);
563 
564  $email_format = $this->getAttribute('receipt_emails_format');
565 
566  // substitute generic keywords with email format-specific keywords
567  $current_value = @unserialize($email_format->value);
568 
569  if (!empty($current_value)) {
570  $current_value['to'] = $receipts;
571  $email_format->value = serialize($current_value);
572 
573  $additional_reps = Array('receipt_address' => '');
574  $this->sendEmail($email_format, $additional_reps);
575  }
576  }
577 
578 
579  // send to a friend
580  if (!empty($stafs)) {
581  // only send one of each type of email to each recipient
582  $stafs = array_unique($stafs);
583 
584  $email_format = $this->getAttribute('staf_format');
585 
586  // substitute generic keywords with email format-specific keywords
587  $current_value = @unserialize($email_format->value);
588 
589  if (!empty($current_value)) {
590  $current_value['to'] = $stafs;
591  $email_format->value = serialize($current_value);
592  $this->sendEmail($email_format);
593  }
594  }
595 
596  return TRUE;
597 
598  }//end runSelectiveEmails()
599 
600 
617  function sendEmail(&$email_format_attr, $replacements=Array())
618  {
619  $current_value = @unserialize($email_format_attr->value);
620  $filenames = Array();
621 
622  // return false if there is no-one to send to
623  if (empty($current_value['to']) && empty($current_value['to_assetids'])) {
624  return FALSE;
625  }
626 
627  // substitute generic keywords with email format-specific keywords
628  $current_value['html_format'] = str_replace(
629  Array('%form_info%', '%form_summary%'),
630  Array('%form_info_html%', '%form_summary_html%'), $current_value['html_format']);
631  $current_value['text_format'] = str_replace(
632  Array('%form_info%', '%form_summary%'),
633  Array('%form_info_text%', '%form_summary_text%'), $current_value['text_format']);
634 
635  // add attachments to emails
636  $current_value['attachments'] = Array();
637  $filenames = Array();
638  if (array_get_index($current_value, 'inc_attachments', FALSE)) {
639  $attachments = $this->_getAttachments();
640  $current_value['attachments'] = $attachments['assets'];
641  $filenames = $attachments['filenames'];
642  }
643 
644  $all_text = $current_value['html_format']
645  .' '.$current_value['text_format']
646  .' '.implode(', ', $current_value['to'])
647  .' '.$current_value['from']
648  .' '.$current_value['reply_to']
649  .' '.$current_value['subject'];
650 
651  $all_keywords = extract_keywords($all_text);
652 
653  if (!is_array($replacements)) $replacements = Array();
654 
655  foreach ($all_keywords as $keyword) {
656  if (isset($replacements[$keyword])) continue;
657  $replacements[$keyword] = $this->_getThankYouKeywordReplacement($keyword);
658  }
659 
660  $email_format_attr->value = serialize($current_value);
661  $email_format_attr->sendMail($replacements, $filenames);
662 
663  }//end sendEmail()
664 
665 
672  public function performSubmissionActions($before_submit = FALSE)
673  {
674  $success = TRUE;
675  $actions = $this->attr('actions');
676  foreach ($actions as $action) {
677  $action_type = $action['type_code'];
678  $GLOBALS['SQ_SYSTEM']->am->includeAsset($action_type);
679 
680  // If need to perform 'before_submit' actions, skip those 'after_submit' action
681  if ($before_submit && !isset($action['settings']['before_submit'])) continue;
682  // If need to perform 'after_submit' actions, skip those 'before_submit' action
683  if (!$before_submit && isset($action['settings']['before_submit'])) continue;
684 
685 
686  if ($action['active'] && call_user_func(Array($action_type, 'isValid'), $this, $action['settings'])) {
687  $success &= call_user_func(Array($action_type, 'execute'), $this, $action['settings']);
688  }
689  }
690 
691  return $success;
692 
693  }//end performSubmissionActions()
694 
695 
706  public function _getThankYouKeywordReplacement($keyword)
707  {
708  $keyword = parse_keyword($keyword, $modifiers);
709  $prefix = $this->getPrefix();
710  $replacement = NULL;
711 
712  // Referrer is used by several keywords below
713  $referrer = (isset($_POST[$prefix.'_referral_url'])) ? $_POST[$prefix.'_referral_url'] : '';
714 
715  if ($keyword == 'referral_url') {
716  $replacement = $referrer;
717  } else if (preg_match('|^referring_asset_(.*)|', $keyword, $matches)) {
718  // referring asset keyword, if we have a Matrix asset URL
719  // eg. %referring_asset_assetid%
720  if (!empty($referrer)) {
721  // use the url to work out the referring asset
722  $referrer = clean_url($referrer);
723 
724  $url_parts = parse_url($referrer);
725  $protocol = array_get_index($url_parts, 'scheme');
726  $path = array_get_index($url_parts, 'host').array_get_index($url_parts, 'path');
727 
728  $referrer_asset = $GLOBALS['SQ_SYSTEM']->am->getAssetFromURL($protocol, $path, TRUE, TRUE);
729  if (!is_null($referrer_asset)) {
730  $referrer_keyword = 'asset_'.$matches[1];
731 
732  $referrer_replacement = $referrer_asset->getKeywordReplacement($referrer_keyword);
733  if ($referrer_replacement !== "%$referrer_keyword%") {
734  $replacement = $referrer_replacement;
735  } else {
736  $replacement = '';
737  }
738  }
739  }//end if referrer is not empty
740 
741  } else if ($keyword == 'youtube_video_link'){
742  $replacement = (isset($this->form_action_keywords['youtube_video_link'])) ? $this->form_action_keywords['youtube_video_link'] : '';
743  } else if ($keyword == 'youtube_video_id'){
744  $replacement = (isset($this->form_action_keywords['youtube_video_id'])) ? $this->form_action_keywords['youtube_video_id'] : '';
745  } else if ($keyword == 'youtube_video_published_date'){
746  $replacement = (isset($this->form_action_keywords['youtube_video_published_date'])) ? $this->form_action_keywords['youtube_video_published_date'] : '';
747  } else {
748  $replacement = parent::_getThankYouKeywordReplacement($keyword);
749  }
750 
751  $replace_keywords = Array(
752  'assetid' => $this->id,
753  'call_fns' => Array ('_getThankYouKeywordReplacement', 'getKeywordReplacement'),
754  );
755  apply_keyword_modifiers($replacement, $modifiers, $replace_keywords);
756 
757  return $replacement;
758 
759  }//end _getThankYouKeywordReplacement()
760 
761 }//end class
762 
763 ?>