Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
form_ecommerce.inc
1 <?php
17 require_once SQ_PACKAGES_PATH.'/cms/form/form_email/form_email.inc';
18 require_once SQ_FUDGE_PATH.'/general/www.inc';
19 require_once SQ_FUDGE_PATH.'/general/file_system.inc';
20 require_once SQ_PACKAGES_PATH.'/ecommerce/orders/order/order.inc';
21 
38 {
39 
44  var $confirm_view = 'confirmation';
45 
50  var $process_view = 'process';
51 
56  var $receipt_view = 'receipt';
57 
62  var $_bodycopies = Array('Form', 'Confirmation', 'Receipt');
63 
64 
71  function Form_Ecommerce($assetid=0)
72  {
73  $this->Form_Email($assetid);
74 
75  }//end constructor
76 
77 
86  function _createAdditional(&$link)
87  {
88  return $this->_createBodycopies();
89 
90  }//end _createAdditional()
91 
92 
99  function _createBodycopies()
100  {
101  $result = TRUE;
102  foreach ($this->_bodycopies as $bodycopy) {
103  $result = $result && $this->createBodycopy($bodycopy);
104  }
105 
106  return $result;
107 
108  }//end _createBodycopies()
109 
110 
119  function _getAllowedLinks()
120  {
121  $order_links = parent::_getAllowedLinks();
122  $order_links[SQ_LINK_TYPE_2]['folder'] = Array('card' => 'M');
123  return $order_links;
124 
125  }//end _getAllowedLinks()
126 
127 
136  function _isAllowedQuestionType($type='')
137  {
138  switch ($type) {
139  case('form_question_type_numeric'):
140  case('form_question_type_select'):
141  case('form_question_type_option_list'):
142  case('form_question_type_tickbox_list'):
143  case('form_question_type_tickbox_table'):
144  return TRUE;
145 
146  default:
147  return FALSE;
148  }
149 
150  }//end _isAllowedQuestionType()
151 
152 
162  {
163  switch ($type) {
164  case('form_question_type_text'):
165  case('form_question_type_numeric'):
166  case('form_question_type_email_address'):
167  case('form_question_type_select'):
168  case('form_question_type_option_list'):
169  case('form_question_type_tickbox_list'):
170  case('form_question_type_tickbox_table'):
171  case('form_question_type_country'):
172  return TRUE;
173 
174  default:
175  return FALSE;
176  }
177 
178  }//end _isAllowedPassThroughQuestionType()
179 
180 
189  function _getEcommerceRule($name='')
190  {
191  // get e-commerce rules
192  $e_questions = $this->attr('rules');
193  $result = array_get_index($e_questions, $name, FALSE);
194  return $result;
195 
196  }//end _getEcommerceRule()
197 
198 
208  function _setEcommerceRule($name, $value)
209  {
210  $rules = $this->attr('rules');
211 
212  if (!isset($rules[$name])) return FALSE;
213 
214  $rules[$name] = $value;
215  $this->setAttrValue('rules', $rules);
216 
217  return TRUE;
218 
219  }//end _setEcommerceRule()
220 
221 
231  function printStandard()
232  {
233  // an order in this case is a state of this form which was saved in a file
234  if (isset($_SESSION[$this->getPrefix()]['order'])) {
235  $order =& $_SESSION[$this->getPrefix()]['order'];
236  } else {
237  $order = $this->_readOrder();
238  }
239 
240  $am =& $GLOBALS['SQ_SYSTEM']->am;
241 
242  // check to see if the form has been submitted or not
243  $action = array_get_index($_REQUEST, $this->getPrefix().'_action');
244  if (isset($_REQUEST[$this->getPrefix().'_submit'])) {
245  if ($this->processPage(1) && empty($action)) {
246  // Save Values for File Uploads and the create File asset if create location is specified
247  $questions =& $this->getAllQuestionAssets();
248  for (reset($questions); $question =& $questions[key($questions)]; next($questions)) {
249  if($question instanceof Form_Question_Type_File_Upload) {
250  $question->saveValue($this);
251  $this->current_answers[$question->id] = $question->getValue();
252  $this->extra_data[$question->id] = $question->getExtraData();
253 
254  if (method_exists($question, 'onSubmitForm')) {
255  $question->onSubmitForm($this);
256  $this->extra_data[$question->id] = $question->getExtraData();
257  if (!empty($question->failed_rules)) {
258  if (!is_array($this->submission_errors)) $this->submission_errors = Array();
259  $this->submission_errors = array_merge($this->submission_errors, $question->failed_rules);
260  }
261  }
262  }
263 
264  }
265  if(empty($this->submission_errors))
266  $action = $this->confirm_view;
267  }
268  } else if (!empty($order)) {
269  //only get the current answers from session variables if we do not process after the submit button is clicked
270  //if we put this block of codes before processPage() method is called like in the previous version, the result
271  //of the answers will be wrong with tickbox list question type (it remembers the previous checked answer not the current unchecked one)
272  $this->current_answers = $order['submission'];
273  $this->extra_data = $order['submission_extra_data'];
274  $this->repopulate();
275  }
276 
277  $request_var_name = $this->attr('item_req_var');
278  if (empty($action) && isset($_REQUEST[$request_var_name])) {
279  $action = 'add_to_cart';
280  }
281 
282  // determine which view to display
283  switch ($action) {
284  case ('add_to_cart'):
285  // MAYBE: Convert to parameter map
286  if ($request_var_name == '') break;
287 
288  $assetid = @$_REQUEST[$request_var_name];
289  if (is_null($assetid)) break;
290 
291  $quantity = @$_REQUEST[$this->attr('item_quantity_req_var')];
292 
293  if (!$this->_addAssetItem($assetid, $quantity)) {
294  trigger_error('This item cannot be purchased', E_USER_NOTICE);
295  break;
296  }
297 
298  $promo_code_var_name = $this->attr('item_promo_code_req_var');
299  if (($promo_code_var_name != '') && isset($_REQUEST[$promo_code_var_name])) {
300  $this->_addAssetItemPromotionalCode($assetid, $_REQUEST[$promo_code_var_name]);
301  }
302 
303  $this->_makeOrder();
304 
305  header('Location: '.$this->getUrl());
306  return TRUE;
307 
308  break;
309 
310  case ('empty_cart'):
311  $this->_clearAssetItems();
313  $this->_makeOrder();
314 
315  header('Location: '.$this->getUrl());
316  return TRUE;
317 
318  break;
319 
320 
321  // confirm view: after the form has been filled out it needs
322  // to be processed and confirmation displayed
323  case ($this->confirm_view):
324  // update order with ecom options
325 
326  $this->_makeOrder();
327  $this->_saveOrder();
328  // we prepare payment processing stuff here instead of in 'process' view
329  // because we might want to nest the payment gateway on this screen
330  // so we need all data to be available to it on this view
331  // side effect of this is that it makes the 'process' view unnecessary if the gateway is nested
332  $order = $_SESSION[$this->getPrefix()]['order'];
333  $action_name = $this->getPrefix().'_action';
334 
335  $_SESSION['SQ_ECOM_SUCCESS_URL'] = $this->getURL().'?'.$action_name.'='.$this->receipt_view;
336  $_SESSION['SQ_ECOM_CANCEL_URL'] = $this->getURL().'?'.$action_name.'='.$this->confirm_view;
337  $_SESSION['SQ_ECOM_REF_NO'] = md5(session_id().time());
338 
339  //Add the pass through variables to SESSION variables
340  $pass_through_vars = $this->_getPassThroughVars();
341  if (!empty($pass_through_vars)) {
342  $_SESSION['SQ_ECOM_PASS_THROUGH_VARS'] = $pass_through_vars;
343  }
344 
345  // if the custom reference id attribtue is not empty it means
346  // that we need a customised reference id
347  $new_reference_id = $this->attr('custom_reference_id');
348  if (!empty($new_reference_id)) {
349  $new_reference_replacements = Array();
350  $new_reference_keywords = extract_keywords($new_reference_id);
351  foreach ($new_reference_keywords as $keyword) {
352  $new_reference_replacements[$keyword] = $this->_getThankYouKeywordReplacement($keyword);
353  }
354 
355  $new_reference_replacements['session_id'] = session_id();
356  $new_reference_replacements['current_time'] = time();
357 
358  replace_keywords($new_reference_id, $new_reference_replacements);
359  // replace_global_keywords($new_reference_id);
360  $_SESSION['SQ_ECOM_REF_NO'] = $new_reference_id;
361  }
362 
363  $_SESSION['SQ_ECOM_AMOUNT'] = $order['total'];
364 
365  $this->printConfirmationView();
366  return TRUE;
367 
368  break;
369 
370 
371  case ('process'):
372  $gateway = $this->attr('gateway_assetid');
373  if (empty($gateway)) {
374  trigger_error('Payment Gateway not configured. Cannot proceed.', E_USER_NOTICE);
375  $this->printConfirmationView();
376  return TRUE;
377  }
378 
379  $gateway = $this->attr('gateway_assetid');
380  $gateway_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($gateway);
381  $gateway_asset_url = $gateway_asset->getURL();
382 
383  header('Location: '.$gateway_asset_url);
384  return TRUE;
385 
386  break;
387 
388 
389  // receipt view: after the gateway has processed payment and redirected back to us
390  // here we need to display the receipt and do the logging, etc
391  case ($this->receipt_view):
392  // check for response from the payment gateway
393  $response = array_get_index($_SESSION, 'SQ_ECOM_RESPONSE', FALSE);
394  if (!$response) {
395  // no response: we've either been here already - user has seen the receipt
396  // or someone has used an invalid url
397  // we redirect because we don't want users being able to refresh the browser
398  header('Location: '.$this->getUrl());
399  return TRUE;
400  }
401 
402 
403 
404  unset($_SESSION['SQ_ECOM_RESPONSE']);
405  $this->_tmp['GATEWAY_RESPONSE'] = $response;
406 
407  // this function is reponsible for doing business logic related to finalizing the
408  // e-commerce transaction: e-mailing, logging and display
409  $order = $this->_readOrder();
410  $this->_deleteOrderFile();
411 
412  $this->current_answers = $order['submission'];
413  $this->extra_data = $order['submission_extra_data'];
414  // re-populate the active submissions
415  $this->repopulate();
416 
417 
418 
419  // CREATE SUBMISSION
420  $this->_saveOrderAsset();
421 
422  // Does two things, depending on whether a create location is set:
423  // Create Location: create a NOTICE link between the File asset and the submission.
424  // No Create Location: Move file upload to the order asset's data directory.
425  $order_asset = $this->order;
426  $file_uploads = $this->getAllQuestionAssets('form_question_type_file_upload');
427 
428  foreach ($file_uploads as $assetid => $file_upload) {
429  $extra_data = $file_upload->getExtraData();
430 
431  $create_location = $file_upload->attr('create_location');
432  if (empty($create_location)) {
433  if (!empty($extra_data['temp_filesystem_path'])) {
434  $filename = $file_upload->getValue();
435  $perm_path = $order_asset->data_path.'/attachments/'.str_replace(':', '_', $file_upload->id);
436 
437  // Move it using Fudge file_system function
438  create_directory($perm_path);
439  move_file($extra_data['temp_filesystem_path'], $perm_path.'/'.$filename);
440  $extra_data = Array(
441  'filesystem_path' => $perm_path.'/'.$filename,
442  );
443 
444  $file_upload->setExtraData($extra_data);
445  // update order asset with uploaded file path
446  $this->_saveOrderAsset();
447  }
448  } else {
449  // create a notice link so we can keep track of uploaded file
450  $uploaded_assetid = array_get_index($extra_data, 'existing_file_assetid', array_get_index($extra_data, 'new_file_assetid', NULL));
451  if (!empty($uploaded_assetid)) {
452  $uploaded_file = $GLOBALS['SQ_SYSTEM']->am->getAsset($uploaded_assetid);
453 
454  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
455  $order_asset->createLink($uploaded_file, SQ_LINK_NOTICE, 'file_submission');
456  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
457  }
458  }
459  // clean up tmp file path since it has been either imported to order asset dir or created as a file asset
460  $file_upload->cleanUp($this);
461  }
462 
463 
464 
465  // log order to file
466  if ($this->attr('log_to_file')) {
467  $this->_logOrderToFile();
468  }
469 
470  // send emails
471  $this->mailReceipt();
472  $this->mailRecipients();
473 
474  // perform submission actions before showing the receipt
475  $this->performSubmissionActions(TRUE);
476 
477  $this->printReceiptView();
478 
479  // clear the cart
480  $_SESSION[$this->getPrefix()]['items'] = Array();
481  $_SESSION[$this->getPrefix()]['order'] = Array();
482  $this->_clearAssetItems();
484 
485  // perform submission actions
486  $this->performSubmissionActions();
487 
488  return TRUE;
489 
490  }//end switch
491 
492 
493  // print the initial form
494  $this->printFormView();
495  return TRUE;
496 
497  }//end printStandard()
498 
499 
506  function _logOrderToFile()
507  {
508  $am =& $GLOBALS['SQ_SYSTEM']->am;
509 
510  $asset_item_format = $this->attr('log_asset_item_format');
511  $question_item_format = $this->attr('log_question_item_format');
512  $item_block_format = $this->attr('log_item_block_format');
513  $log_entry_format = $this->attr('log_entry_format');
514 
515  ob_start();
516 
517  $asset_list = @$_SESSION[$this->getPrefix()]['order']['ecom_assets'];
518  if (empty($asset_list)) $asset_list = Array();
519  foreach ($asset_list as $id => $item) {
520  $asset = $am->getAsset($id);
521  $item_string = $asset->replaceKeywordsInString($asset_item_format);
522  $replacements['item_name'] = $item['name'];
523  $replacements['item_price'] = $item['price'];
524  $replacements['item_id'] = $item['id'];
525  replace_keywords($item_string, $replacements);
526  echo $item_string;
527  }
528  $asset_item_list = ob_get_clean();
529  $item_block_replacements['asset_item_list'] = $asset_item_list;
530 
531  ob_start();
532  $question_list = @$_SESSION[$this->getPrefix()]['order']['ecom_questions'];
533  if (empty($question_list)) $question_list = Array();
534  foreach ($question_list as $id => $item) {
535  $item_string = $question_item_format;
536  $replacements['item_name'] = $item['name'];
537  $replacements['item_price'] = $item['price'];
538  $replacements['item_id'] = $item['id'];
539  replace_keywords($item_string, $replacements);
540  echo $item_string;
541  }
542  $question_item_list = ob_get_clean();
543  $item_block_replacements['question_item_list'] = $question_item_list;
544 
545  $item_block = '';
546  if (!empty($question_item_list) || !empty($asset_item_list)) {
547  $item_block = $item_block_format;
548  replace_keywords($item_block, $item_block_replacements);
549  }
550 
551  $log_entry_string = $log_entry_format;
552  $log_entry_keywords = extract_keywords($log_entry_format);
553  foreach ($log_entry_keywords as $keyword) {
554  if ($keyword == 'form_summary') {
555  $keyword2 = $keyword.'_text';
556  $log_entry_replacements[$keyword] = $this->_getThankYouKeywordReplacement($keyword2);
557  } else {
558  $log_entry_replacements[$keyword] = $this->_getThankYouKeywordReplacement($keyword);
559  }
560  }
561 
562  $log_entry_replacements['item_block'] = $item_block;
563  $log_entry_replacements['order_id'] = $this->getOrderNumberKeywordReplacement();
564  replace_keywords($log_entry_string, $log_entry_replacements);
565 
566  replace_global_keywords($log_entry_string);
567 
568  // write to log
569  $this->_log($log_entry_string);
570 
571  }//end _logOrderToFile()
572 
573 
580  function printBody()
581  {
582  $this->printStandard();
583 
584  }//end printBody()
585 
586 
593  function printFormView()
594  {
595  $prefix = $this->getPrefix();
596 
597  $clientside = ($this->attr('use_client_side')) ? 'onsubmit="return beforeSubmit_'.$prefix.'(this);"' : '';
598 
599  $form_action = $_SERVER['PHP_SELF'];
600 
601  // Add the query string as well if it exists, so asset references with ?a=###
602  // submit back to themselves.
603  if (!empty($_SERVER['QUERY_STRING'])) {
604  $form_action .= '?'.htmlentities($_SERVER['QUERY_STRING']);
605  }
606 
607  ob_start();
608  if ($this->attr('use_client_side')) {
609  ?><script type="text/javascript">
610  function beforeSubmit_<?php echo $prefix; ?>(form) {
611  var submission_errors = new Array();
612  i = 0;
613  <?php echo $this->generateJSCode(); ?>
614  if (submission_errors.length > 0) {
615  var errors_list = "<?php echo translate('cms_form_submission_errors'); ?>\n";
616  for(x in submission_errors) {
617  errors_list += submission_errors[x] + "\n";
618  }
619  alert(errors_list);
620  return false;
621  }
622  return true;
623  }
624  </script>
625  <?php
626  }
627  $javascript = ob_get_clean();
628 
629  $bodycopy =& $this->getBodycopy('Form');
630 
631  if (is_null($bodycopy)) return '';
632 
633  $replacements = Array();
634  $keyword_list = $bodycopy->getKeywords();
635  if (!empty($keyword_list)) {
636  foreach ($keyword_list as $keyword) {
637  if (isset($replacements[$keyword])) continue;
638  $replacements[$keyword] = $this->getKeywordReplacement($keyword);
639  }
640  }
641 
642  $bodycopy->setKeywordReplacements($replacements);
643 
644  // all the output is here
645  echo '<form id="'.$prefix.'" enctype="multipart/form-data" action="'.$form_action.'" method="post" '.$clientside.'>';
646  echo $javascript;
647  echo hidden_field('SQ_FORM_'.$this->id.'_PAGE', 1);;
648  $bodycopy->printBody();
649  echo '</form>';
650 
651  }//end printFormView()
652 
653 
662  function getKeywordReplacement($keyword)
663  {
664  $value = NULL;
665  $unreplaced_value = '%'.$keyword.'%';
666 
667  $keyword_parts = explode('_', $keyword);
668  if (empty($keyword_parts)) return $unreplaced_value;
669 
670  $keyword_category = $keyword_parts[0];
671 
672  if ($keyword_category == 'question') {
673 
674  // keywords look like this:
675  // question_TYPE_BRIDGEID_qQUESTIONID
676  // where TYPE = id, label, field, note
677 
678  if (count($keyword_parts) != 4) {
679  return $unreplaced_value;
680  }
681 
682  $question_id = $keyword_parts[2].':'.$keyword_parts[3];
683 
684  if (!$this->isAllowedQuestionId($question_id)) {
685  return $unreplaced_value;
686  }
687 
688  $q_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($question_id);
689 
690  switch ($keyword_parts[1]) {
691  case 'id':
692  $value = 'q'.$keyword_parts[2].'_'.$keyword_parts[3];
693  break;
694 
695  case 'label':
696  $value = $q_asset->getHtmlLabel();
697  break;
698 
699  case 'field':
700  $value = $q_asset->getHtmlField();
701  break;
702 
703  case 'note':
704  $value = $q_asset->attr('note');
705  break;
706 
707  case 'response':
708  $value = $q_asset->getSummary();
709  break;
710 
711  case 'name':
712  $value = $q_asset->attr('name');
713  break;
714 
715  default:
716  $value = $unreplaced_value;
717  }
718 
719  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($q_asset);
720 
721  return $value;
722 
723  } else if ($keyword_category == 'response') {
724  if (count($keyword_parts) != 3) {
725  return $unreplaced_value;
726  }
727 
728  $question_id = $keyword_parts[1].':'.$keyword_parts[2];
729  if (!$this->isAllowedQuestionId($question_id)) {
730  return $unreplaced_value;
731  }
732 
733  $q_asset =& $GLOBALS['SQ_SYSTEM']->am->getAsset($question_id);
734  $value = $q_asset->getSummary();
735  return $value;
736 
737  } else if ($keyword_category == 'section') {
738  // section keyword looks like this:
739  // section_title_SECTIONID
740 
741  if (count($keyword_parts) != 3) {
742  return $unreplaced_value;
743  }
744 
745  if ($keyword_parts[1] == 'title') {
746  $section_id = $keyword_parts[2];
747  $section_asset =& $GLOBALS['SQ_SYSTEM']->am->getAsset($section_id);
748  $value = $section_asset->attr('name');
749  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($section_asset);
750 
751  return $value;
752  }
753  }
754 
755  return parent::getKeywordReplacement($keyword);
756 
757  }//end getKeywordReplacement()
758 
759 
770  function isAllowedQuestionId($question_id)
771  {
772  $all_questions = $this->getAllQuestionsCached();
773  return isset($all_questions[$question_id]);
774 
775  }//end isAllowedQuestionId()
776 
777 
787  {
788  if (is_null(@$this->_tmp['all_questions'])) {
789  $this->_tmp['all_questions'] = $this->getAllQuestions();
790  }
791 
792  $questions =& $this->_tmp['all_questions'];
793 
794  return $questions;
795 
796  }//end getAllQuestionsCached()
797 
798 
808  {
809  // check to see if the bodycopy attached to this form has any content
810  $questions = $this->getQuestions();
811  $sections =& $this->getSections();
812 
813  foreach ($questions as $q_id => $question) {
814  $q_asset =& $GLOBALS['SQ_SYSTEM']->am->getAsset($this->id.':q'.$q_id);
815  $q_name = $q_asset->attr('name');
816  $replacements['question_field_'.$this->id.'_q'.$q_id] = $q_asset->getHtmlField();
817  $replacements['question_id_'.$this->id.'_q'.$q_id] = 'q'.$this->id.'_q'.$q_id;
818  $replacements['question_note_'.$this->id.'_q'.$q_id] = $q_asset->attr('note');
819  $replacements['question_label_'.$this->id.'_q'.$q_id] = $q_asset->getHtmlLabel();
820  }
821 
822  foreach ($sections as $section) {
823  $replacements['section_title_'.$section->id] = $section->attr('name');
824  $questions = $section->getQuestions();
825  foreach ($questions as $q_id => $question) {
826  $q_asset =& $GLOBALS['SQ_SYSTEM']->am->getAsset($section->id.':q'.$q_id);
827  $q_name = $section->attr('name').': '.$q_asset->attr('name');
828  $replacements['question_field_'.$section->id.'_q'.$q_id] = $q_asset->getHtmlField();
829  $replacements['question_id_'.$section->id.'_q'.$q_id] = 'q'.$section->id.'_q'.$q_id;
830  $replacements['question_note_'.$section->id.'_q'.$q_id] = $q_asset->attr('note');
831  $replacements['question_label_'.$section->id.'_q'.$q_id] = $q_asset->getHtmlLabel();
832  }
833  }
834 
835  return $replacements;
836 
837  }//end _getCommonFormKeywordReplacements()
838 
839 
848  function &getBodycopy($bodycopy)
849  {
850  if ($bodycopy == 'Page Contents') {
851  $bodycopy = 'Form';
852  } else if ($bodycopy == 'Thank You') {
853  $bodycopy = 'Confirmation';
854  }
855 
856  $bodycopy_asset =& parent::getBodycopy($bodycopy);
857 
858  return $bodycopy_asset;
859 
860  }//end getBodycopy()
861 
862 
870  {
871  return $this->_getPageContentsBodycopyKeywords();
872 
873  }//end _getFormBodycopyKeywords()
874 
875 
883  {
884  return $this->_getThankYouBodycopyKeywords();
885 
886  }//end _getConfirmationBodycopyKeywords()
887 
888 
896  {
897  return $this->_getThankYouBodycopyKeywords();
898 
899  }//end _getReceiptBodycopyKeywords()
900 
901 
908  function &createSubmission()
909  {
910  return ($order =& $this->createOrder());
911 
912  }//end createSubmission()
913 
914 
923  function _getReceiptHeader($as_html=TRUE)
924  {
925  $header = '';
926 
927  // get response from the gateway
928  $response = array_get_index($this->_tmp, 'GATEWAY_RESPONSE', FALSE);
929  if (!$response) return $header;
930 
931  // today
932  $date = date('F j, Y, g:i a');
933 
934  if ($as_html) {
935  $header ='
936  <table class="ecom_header_table">
937  <tr>
938  <td colspan="2"><h2>Receipt</h2></td>
939  </tr>
940  <tr>
941  <td>'.translate('ecom_form_transaction_number:').'</td>
942  <td>'.$response['TRANSACTION'].'</td>
943  </tr>
944  <tr>
945  <td>'.translate('ecom_form_transaction_status:').'</td>
946  <td>'.$response['STATUS'].'</td>
947  </tr>
948  <tr>
949  <td>'.translate('ecom_form_credit_card:').'</td>
950  <td>'.$response['CARDNO'].'</td>
951  </tr>
952  <tr>
953  <td>'.translate('ecom_form_date:').'</td>
954  <td>'.$date.'</td>
955  </tr>
956  </table>
957  ';
958 
959  } else {
960  $header .= translate('ecom_form_transaction_number:').' '.$response['TRANSACTION']."\n";
961  $header .= translate('ecom_form_transaction_status:').' '.$response['STATUS']."\n";
962  $header .= translate('ecom_form_date:').' '.$date."\n";
963  }
964 
965  return $header;
966 
967  }//end _getReceiptHeader()
968 
969 
980  function printSummary($as_html=FALSE)
981  {
982  echo $this->_getReceiptHeader($as_html);
983  echo $this->_getReceipt($as_html);
984  if ($as_html) {
985  echo '<br /><br />';
986  } else {
987  echo "\n\n";
988  }
989  parent::printSummary($as_html);
990 
991  }//end printSummary()
992 
993 
1000  function processForm()
1001  {
1002  return parent::processPage(1);
1003 
1004  }//end processForm()
1005 
1006 
1013  function _saveOrderAsset()
1014  {
1015  $questions =& $this->getAllQuestionAssets();
1016 
1017  $order =& $this->getCurrentOrderAsset();
1018  if (is_null($order)) $order =& $this->createOrder();
1019 
1020 
1021  $this->order =& $order;
1022  $this->submission_asset =& $order;
1023 
1024 
1025  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
1026  // save question values
1027  for (reset($questions); $question =& $questions[key($questions)]; next($questions)) {
1028  $question->saveValue($this);
1029 
1030  // If the question is sticky, stick the value then
1031  if ($question->attr('sticky')) {
1032  $question->stickValue($question->getValue());
1033  }
1034  }
1035 
1036  // create the submission asset
1037  for (reset($questions); $question =& $questions[key($questions)]; next($questions)) {
1038  $order->setAnswer(key($questions), $question->getValue());
1039  $order->setSummary(key($questions), $question->attr('name'), $question->getSummary());
1040  $order->setExtraData(key($questions), $question->getExtraData());
1041  }
1042 
1043  $order->setIP($_SERVER['REMOTE_ADDR']);
1044  $order->setAttrValue('complete', TRUE);
1045  $order->setAttrValue('xml', $this->getXML());
1046  //set ecommerce order's details
1047  $order->setAttrValue('transaction_id', array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'TRANSACTION', ''));
1048  $order->setAttrValue('billing_name', array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'BILLING_NAME', ''));
1049  $order->setAttrValue('billing_addr', array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'BILLING_ADDR', ''));
1050  $order->setAttrValue('delivery_name', array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'DELIVERY_NAME', ''));
1051  $order->setAttrValue('delivery_addr', array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'DELIVERY_ADDR', ''));
1052 
1053  $order->saveAttributes();
1054 
1055  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1056 
1057  }//end _saveOrderAsset()
1058 
1059 
1066  function &createOrder()
1067  {
1068  $am =& $GLOBALS['SQ_SYSTEM']->am;
1069 
1070  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
1071  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
1072 
1073  // search for a bodycopies folder and create one if there isn't one there
1074  $folder_link = $GLOBALS['SQ_SYSTEM']->am->getLink($this->id, SQ_LINK_TYPE_2, 'folder', TRUE, 'orders_folder');
1075  if (empty($folder_link)) {
1076 
1077  // create a folder for the bodycopies
1078  $GLOBALS['SQ_SYSTEM']->am->includeAsset('folder');
1079  $folder = new Folder();
1080  $folder->setAttrValue('name', 'Orders');
1081 
1082  $folder_link = Array('asset' => &$this, 'link_type' => SQ_LINK_TYPE_2, 'value' => 'orders_folder', 'is_dependant' => 0, 'is_exclusive' => 1);
1083 
1084  // Create order folder
1085  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
1086  $success = $folder->create($folder_link);
1087  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
1088  if (!$success) {
1089  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1090  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1091  return FALSE;
1092  }
1093 
1094  // Deny public read access to the order folder by default
1095  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
1096  $success = $GLOBALS['SQ_SYSTEM']->am->setPermission($folder->id, $GLOBALS['SQ_SYSTEM']->am->getSystemAssetid('public_user'), SQ_PERMISSION_READ, 0, TRUE, TRUE);
1097  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
1098  if (!$success) {
1099  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1100  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1101  return FALSE;
1102  }
1103 
1104  } else {
1105  // folder already exists, get the reference
1106  $folder = $GLOBALS['SQ_SYSTEM']->am->getAsset($folder_link['minorid'], $folder_link['minor_type_code']);
1107  }
1108 
1109 
1110  if (is_null($folder)) {
1111  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1112  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1113  return FALSE;
1114  }
1115 
1116  // create the Order asset
1117  $order = new Order();
1118  $copy_link = Array('asset' => &$folder, 'link_type' => SQ_LINK_TYPE_2, 'is_dependant' => 1, 'is_exclusive' => 1);
1119 
1120  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
1121  $success = $order->create($copy_link);
1122  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
1123 
1124  // attempt to create the link to this asset
1125  if (!$success) {
1126  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1127  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1128  return FALSE;
1129  }
1130  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
1131  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1132 
1133  return $order;
1134 
1135  }//end createOrder()
1136 
1137 
1146  function _getReceipt($as_html=TRUE)
1147  {
1148  $order = $_SESSION[$this->getPrefix()]['order'];
1149  if (empty($order)) return FALSE;
1150 
1151  $curr_sign = $this->attr('currency_sign');
1152  if ($as_html) {
1153  $receipt_fmt = '<hr /><table class="sq_ecomTable">%s%s%s</table><hr />';
1154  $order_row_fmt = '<tr class="sq_ecomTableItemRow"><td class="sq_ecomTableItemName">%s</td><td class="sq_ecomTableItemValue" align="right">%01.2f</td></tr>';
1155  $divider_row = '<tr class="sq_ecomTableItemRow"><td class="sq_ecomTableItemName">&nbsp;</td><td class="sq_ecomTableItemValue" align="right"><hr /></td></tr>';
1156  $total_discount_row_fmt = '<tr class="sq_ecomTableTotalDiscountRow"><td class="sq_ecomTableTotalDiscountName" align="right">%s</td><td class="sq_ecomTableTotalDiscountValue" align="right">'.$curr_sign.'%01.2f</td></tr>';
1157  $total_row_fmt = '<tr class="sq_ecomTableTotalRow"><td class="sq_ecomTableTotalName" align="right">%s</td><td class="sq_ecomTableTotalValue" align="right">'.$curr_sign.'%01.2f</td></tr>';
1158  } else {
1159  $receipt_fmt = strtoupper(translate('ecom_form_receipt:'))."\n############################\n%s\n%s\n%s\n############################";
1160  $order_row_fmt = "%s: %01.2f\n";
1161  $divider_row = "----------------------------\n";
1162  $total_discount_row_fmt = "*** %s $curr_sign%01.2f ***\n";
1163  $total_row_fmt = "*** %s $curr_sign%01.2f ***\n";
1164  }
1165 
1166  $rows = '';
1167  foreach ($order['items'] as $item) {
1168  $rows .= sprintf($order_row_fmt, $item['name'], $item['price']);
1169  }
1170 
1171  $rows .= $divider_row;
1172 
1173  $total_discount = '';
1174  if ($order['total_discount'] > 0) {
1175  $total_discount = sprintf($total_discount_row_fmt, translate('ecom_form_total_discount:'), $order['total_discount']);
1176  $total_discount .= $divider_row;
1177  }
1178 
1179  $total = sprintf($total_row_fmt, translate('ecom_form_total:'), $order['total']);
1180  $receipt = sprintf($receipt_fmt, $rows, $total_discount, $total);
1181 
1182  return $receipt;
1183 
1184  }//end _getReceipt()
1185 
1186 
1193  function _makeOrder()
1194  {
1195  $total = 0;
1196  $taxable_total = 0;
1197  $total_discount = 0;
1198 
1199  $questions =& $this->getAllQuestionAssets();
1200  $ecom_items = Array();
1201  $taxable_items = Array();
1202  $ecom_assets = Array();
1203  $ecom_questions = Array();
1204 
1205  // process the assets being purchased
1206  $am =& $GLOBALS['SQ_SYSTEM']->am;
1207  $assets_in_cart = $this->_getAssetItems();
1208  $promo_codes_in_cart = $this->_getAssetItemPromotionalCodes();
1209  foreach ($assets_in_cart as $asset_id => $count) {
1210  $ecom_item['taxable'] = FALSE;
1211  $asset = $am->getAsset($asset_id);
1212  $name = $this->_getPurchasableAssetName($asset);
1213  $price = $this->_getPurchasableAssetPrice($asset);
1214 
1215  // process promotional codes
1216  $discount = 0;
1217  if (isset($promo_codes_in_cart[$asset_id])) {
1218  $discount = $this->_getPromotionalCodeDiscount($promo_codes_in_cart[$asset_id], $price, $count);
1219  }
1220 
1221  if ($count > 1) {
1222  $name = $count.' x '.$name.' @'.$price;
1223  $price = $price * $count;
1224  }
1225 
1226  $ecom_item['name'] = $name;
1227  $ecom_item['quantity'] = $count;
1228  $ecom_item['price'] = $price;
1229  $ecom_item['discount'] = $discount;
1230  $ecom_item['id'] = $asset_id;
1231 
1232  $is_taxable = $this->_isPurchasableAssetTaxable($asset);
1233 
1234  if ($is_taxable) {
1235  $taxable_items[$asset_id] = $ecom_item;
1236  $taxable_total += $ecom_item['price'];
1237  $ecom_item['taxable'] = TRUE;
1238  }
1239  $ecom_assets[$asset_id] = $ecom_item;
1240  $ecom_items[$asset_id] = $ecom_item;
1241  $total += $ecom_item['price'];
1242  $total_discount += $ecom_item['discount'];
1243  $am->forgetAsset($asset);
1244  }
1245 
1246  // now process the ecommerce questions
1247  $taxable_rules = $this->attr('taxable_rules');
1248 
1249  foreach ($questions as $q_id => $question) {
1250  if (($rule = $this->_getEcommerceRule($q_id)) !== FALSE) {
1251  $ecom_item['taxable'] = FALSE;
1252  $question_title = $question->attr('name');
1253  // if it is a selection question, we ask the question to
1254  // tell us if an option was selected
1255 
1256  // Reset the var here because we are going to overwrite them anyway
1257  $ecom_item['name'] = '';
1258  $ecom_item['price'] = '';
1259  if ($question->isSelection()) {
1260  foreach ($rule as $option_id => $price) {
1261  //if option is selcted and option is not --leave empty--
1262  if ($question->isSelected($option_id) && (!($question instanceof Form_question_type_select) || !$question->isEmptyOption($option_id))) {
1263  if (isset($ecom_item['name']) && !empty($ecom_item['name'])) {
1264  $ecom_item['name'] .= ', '.$question->getOptionName($option_id);
1265  } else {
1266  $ecom_item['name'] = $question_title.': '.$question->getOptionName($option_id);
1267  }//end if else
1268  if (!isset($ecom_item['price']) && !empty($ecom_item['price'])) {
1269  $ecom_item['price'] = $price;
1270  } else {
1271  $ecom_item['price'] += $price;
1272  }//end if
1273 
1274  $ecom_item['id'] = $q_id;
1275 
1276  if (array_get_index($taxable_rules, $q_id, FALSE)) {
1277  $taxable_items[$q_id] = $ecom_item;
1278  $taxable_total += $price;
1279  $ecom_item['taxable'] = TRUE;
1280  }
1281  $ecom_items[$q_id] = $ecom_item;
1282  $ecom_questions[$q_id] = $ecom_item;
1283  $total += $price;
1284  }
1285  }
1286 
1287  } else {
1288  // if it is not a question with options, we get the submission directly
1289  // we assume that it is a numeric question
1290  $ecom_item['name'] = $question_title;
1291  $ecom_item['price'] = $this->current_answers[$q_id];
1292  $ecom_item['id'] = $q_id;
1293 
1294  if (array_get_index($taxable_rules, $q_id, FALSE)) {
1295  $taxable_items[$q_id] = $ecom_item;
1296  $taxable_total += $ecom_item['price'];
1297  $ecom_item['taxable'] = TRUE;
1298  }
1299  $ecom_items[$q_id] = $ecom_item;
1300  $ecom_questions[$q_id] = $ecom_item;
1301  $total += $ecom_item['price'];
1302  }//end if
1303 
1304  }//end if
1305 
1306  }//end foreach
1307 
1308  $order['items'] = $ecom_items;
1309  $order['ecom_assets'] = $ecom_assets;
1310  $order['ecom_questions'] = $ecom_questions;
1311  $order['taxable_items'] = $taxable_items;
1312  $order['taxable_total'] = $taxable_total;
1313  $order['total'] = $total - $total_discount;
1314  $order['total_discount'] = $total_discount;
1315  $order['submission'] = $this->current_answers;
1316  $order['submission_extra_data'] = $this->extra_data;
1317 
1318  $_SESSION[$this->getPrefix()]['order'] = $order;
1319 
1320  return TRUE;
1321 
1322  }//end _makeOrder()
1323 
1324 
1331  function _saveOrder()
1332  {
1333  $filename = $this->_getOrderFileName();
1334  $order = $_SESSION[$this->getPrefix()]['order'];
1335  $order_contents = serialize($order);
1336  return string_to_file($order_contents, $filename);
1337 
1338  }//end _saveOrder()
1339 
1340 
1347  function _readOrder()
1348  {
1349  $filename = $this->_getOrderFileName();
1350  $order = file_to_string($filename);
1351  if (!$order) return FALSE;
1352  $_SESSION[$this->getPrefix()]['order'] = unserialize($order);
1353  return $_SESSION[$this->getPrefix()]['order'];
1354 
1355  }//end _readOrder()
1356 
1357 
1365  function _deleteOrderFile()
1366  {
1367  $filename = $this->_getOrderFileName();
1368  unlink($filename);
1369  return TRUE;
1370 
1371  }//end _deleteOrderFile()
1372 
1373 
1385  function _getOrderFileName($order_no=FALSE)
1386  {
1387  $order_path = $this->data_path.'/tmp_orders';
1388 
1389  if (!is_dir($order_path)) {
1390  mkdir($order_path);
1391  chmod($order_path, 0700);
1392  }
1393 
1394  if (!$order_no) $order_no = session_id();
1395 
1396  return $order_path.'/'.$order_no.'.tmp';
1397 
1398  }//end _getOrderFileName()
1399 
1400 
1408  {
1409  $body =& $this->getBodycopy('Confirmation');
1410 
1411  $keyword_list = $body->getKeywords();
1412  $replacements = Array();
1413  foreach ($keyword_list as $keyword) {
1414  $replacements[$keyword] = $this->_getThankYouKeywordReplacement($keyword == 'form_summary' ? 'form_summary_text' : $keyword);
1415  }
1416 
1417  $body->setKeywordReplacements($replacements);
1418  $body->printBody();
1419 
1420  }//end printConfirmationView()
1421 
1422 
1429  function printReceiptView()
1430  {
1431  $body = $this->getBodycopy('Receipt');
1432  $replacements = Array();
1433 
1434  $keyword_list = $body->getKeywords();
1435  foreach ($keyword_list as $keyword) {
1436  $replacements[$keyword] = $this->_getThankYouKeywordReplacement($keyword == 'form_summary' ? 'form_summary_text' : $keyword);
1437  }
1438 
1439  $body->setKeywordReplacements($replacements);
1440  $body->printBody();
1441 
1442  }//end printReceiptView()
1443 
1444 
1452  {
1453  $parent_page_assetid = array_get_index($this->_tmp, 'parent_form_page_assetid');
1454 
1455  if (is_null($parent_page_assetid)) {
1456  $parents = array_keys($GLOBALS['SQ_SYSTEM']->am->getParents($this->id, 'page_custom_form_ecommerce', FALSE));
1457  $parent_page_assetid = array_pop($parents);
1458  $this->_tmp['parent_form_page_assetid'] =& $parent_page_assetid;
1459  }
1460 
1461  return $parent_page_assetid;
1462 
1463  }//end _getParentPageAssetId()
1464 
1465 
1473  {
1474  if (!isset($this->_tmp['parent_form_page_asset'])) {
1475  $parent_page = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->_getParentPageAssetId());
1476  $this->_tmp['parent_form_page_asset'] =& $parent_page;
1477  } else {
1478  $parent_page =& $this->_tmp['parent_form_page_asset'];
1479  }
1480 
1481  return $parent_page;
1482 
1483  }//end _getParentPageAsset()
1484 
1485 
1494  function getUrl()
1495  {
1496  $url = array_get_index($this->_tmp, 'current_url');
1497 
1498  if (is_null($url)) {
1499  $parent =& $this->_getParentPageAsset();
1500  $url = $parent->getURL();
1501 
1502  $this->_tmp['current_url'] = $url;
1503  }
1504 
1505  return $url;
1506 
1507  }//end getUrl()
1508 
1509 
1510 //-- KEYWORDS AVAILABLE --//
1511 
1512 
1520  {
1521  $keywords = parent::_getThankYouBodycopyKeywords();
1522 
1523  $keywords['confirm_text'] = 'Confirm and pay button text';
1524  $keywords['cancel_text'] = 'Text Used on "Cancel" button';
1525 
1526  $keywords['confirm_url'] = 'URL to Confirmation Screen';
1527  $keywords['cancel_url'] = 'URL to Cancel Screen';
1528 
1529  $keywords['order_item_count'] = 'Count of items being purchased';
1530  $keywords['order_total'] = 'Total';
1531  $keywords['order_total_excluding_tax'] = 'Total minus tax';
1532  $keywords['order_total_tax'] = 'Total tax';
1533  $keywords['order_taxable_total'] = 'Taxable total';
1534  $keywords['order_taxable_item_count'] = 'Count of taxable items being purchased';
1535  $keywords['order_item_list'] = 'List of items being purchased';
1536  $keywords['order_total_discount'] = 'Total discount';
1537  $keywords['order_total_before_discount'] = 'Total before discount';
1538 
1539  $keywords['tax_rate'] = 'Tax Rate';
1540  $keywords['tax_name'] = 'Tax Name';
1541 
1542  $keywords['taxable_item_string'] = 'String appended to the taxable items';
1543 
1544  return $keywords;
1545 
1546  }//end _getThankYouBodycopyKeywords()
1547 
1548 
1549 //-- KEYWORD REPLACEMENT FUNCTIONS --//
1550 
1551 
1559  {
1560  return $this->attr('confirm_button_name');
1561 
1562  }//end getConfirmTextKeywordReplacement()
1563 
1564 
1572  {
1573  return $this->attr('cancel_button_name');
1574 
1575  }//end getCancelTextKeywordReplacement()
1576 
1577 
1585  {
1586  $confrim_url = $this->getUrl();
1587  $confrim_url .= '?'.$this->getPrefix().'_action=process';
1588 
1589  return $confrim_url;
1590 
1591  }//end getConfirmUrlKeywordReplacement()
1592 
1593 
1601  {
1602  $cancel_url = $this->getUrl();
1603 
1604  return $cancel_url;
1605 
1606  }//end getCancelUrlKeywordReplacement()
1607 
1608 
1616  {
1617  $item_count = 0;
1618 
1619  if (isset($_SESSION[$this->getPrefix()]['order']['items'])) {
1620  $item_count = count($_SESSION[$this->getPrefix()]['order']['items']);
1621  }
1622 
1623  return $item_count;
1624 
1625  }//end getOrderItemCountKeywordReplacement()
1626 
1627 
1635  {
1636  $total = $this->_getTotal();
1637  $total = $this->_formatPriceAmount($total);
1638 
1639  return $total;
1640 
1641  }//end getOrderTotalKeywordReplacement()
1642 
1643 
1651  {
1652  $total_discount = $this->_getTotalDiscount();
1653  $total_discount = $this->_formatPriceAmount($total_discount);
1654 
1655  return $total_discount;
1656 
1657  }//end getOrderTotalDiscountKeywordReplacement()
1658 
1659 
1667  {
1668  $total = $this->_getTotal();
1669  $total_discount = $this->_getTotalDiscount();
1670  $total_before_discount = $total + $total_discount;
1671  $total_before_discount = $this->_formatPriceAmount($total_before_discount);
1672 
1673  return $total_before_discount;
1674 
1675  }//end getOrderTotalBeforeDiscountKeywordReplacement()
1676 
1677 
1678 
1686  {
1687  $total = $this->_getTotal();
1688 
1689  $tax = $this->_getTaxTotal();
1690  $total_no_tax = $total - $tax;
1691  $total_no_tax = $this->_formatPriceAmount($total_no_tax);
1692 
1693  return $total_no_tax;
1694 
1695  }//end getOrderTotalExcludingTaxKeywordReplacement()
1696 
1697 
1705  {
1706  $total_tax = $this->_formatPriceAmount($this->_getTaxTotal());
1707 
1708  return $total_tax;
1709 
1710  }//end getOrderTotalTaxKeywordReplacement()
1711 
1712 
1720  {
1721  $taxable_total = $this->_formatPriceAmount($this->_getTaxableTotal());
1722 
1723  return $taxable_total;
1724 
1725  }//end getOrderTaxableTotalKeywordReplacement()
1726 
1727 
1735  {
1736  $taxable_count = 0;
1737 
1738  if (isset($_SESSION[$this->getPrefix()]['order']['taxable_items'])) {
1739  $taxable_count = count($_SESSION[$this->getPrefix()]['order']['taxable_items']);
1740  }
1741  return $taxable_count;
1742 
1743  }//end getOrderTaxableItemCountKeywordReplacement()
1744 
1745 
1753  {
1754  return $this->_getTaxRate();
1755 
1756  }//end getTaxRateKeywordReplacement()
1757 
1758 
1766  {
1767  return $this->attr('tax_name');
1768 
1769  }//end getTaxNameKeywordReplacement()
1770 
1771 
1779  {
1780  $item_format = $this->attr('item_format');
1781  $keywords = extract_keywords($item_format);
1782 
1783  ob_start();
1784  foreach ($this->_getOrderItems() as $item) {
1785  $item_line = $item_format;
1786 
1787  $item_name = array_get_index($item, 'name', '--UNKNOWN ITEM NAME--');
1788  $item_price = array_get_index($item, 'price', 0);
1789  $item_id = array_get_index($item, 'id');
1790  $is_taxable = array_get_index($item, 'taxable', FALSE);
1791 
1792  $replacements['item_name'] = $item_name;
1793  $replacements['item_price'] = $this->_formatPriceAmount($item_price);
1794  $replacements['currency_sign'] = $this->attr('currency_sign');
1795  $replacements['item_taxable_string'] = '';
1796  if ($is_taxable) {
1797  $replacements['taxable_item_string'] = $this->attr('item_taxable_string');
1798  }
1799  replace_keywords($item_line, $replacements);
1800 
1801  echo $item_line;
1802  }
1803 
1804  return ob_get_clean();
1805 
1806  }//end getOrderItemListKeywordReplacement()
1807 
1808 
1816  {
1817  $am =& $GLOBALS['SQ_SYSTEM']->am;
1818  $assets_in_cart = $this->_getAssetItems();
1819 
1820  $item_format = $this->attr('form_asset_format');
1821 
1822  ob_start();
1823  foreach ($assets_in_cart as $asset_id => $count) {
1824  $asset =& $am->getAsset($asset_id);
1825 
1826  $price = $this->_getPurchasableAssetPrice($asset);
1827  $name = $this->_getPurchasableAssetName($asset);
1828  $is_taxable = $this->_isPurchasableAssetTaxable($asset);
1829 
1830  if ($count > 1) {
1831  $name = $count.' x '.$name.' @'.$price;
1832  $price = $price * $count;
1833  }
1834 
1835  $replacements['item_name'] = $name;
1836  $replacements['item_price'] = $this->_formatPriceAmount($price);
1837  $replacements['currency_sign'] = $this->attr('currency_sign');
1838  $replacements['item_taxable_string'] = '';
1839  if ($is_taxable) {
1840  $replacements['taxable_item_string'] = $this->attr('item_taxable_string');
1841  }
1842 
1843  // ask asset to replace any known keywords
1844  $item_line = $asset->replaceKeywordsInString($item_format);
1845  // replace those new keywords the asset doesn't know about
1846  replace_keywords($item_line, $replacements);
1847 
1848  echo $item_line;
1849  }
1850 
1851  return ob_get_clean();
1852 
1853  }//end getOrderPurchasableAssetListKeywordReplacement()
1854 
1855 
1863  {
1864  $item_printout = $this->getOrderPurchasableAssetListKeywordReplacement();
1865  if (empty($item_printout)) {
1866  return $this->attr('form_assets_empty_str');
1867  }
1868 
1869  $form_assets_format = $this->attr('form_asset_list_format');
1870  $keywords['item_format'] = $item_printout;
1871  replace_keywords($form_assets_format, $keywords);
1872 
1873  return $form_assets_format;
1874 
1875  }//end getItemListingKeywordReplacement()
1876 
1877 
1885  {
1886  return $this->attr('item_taxable_string');
1887 
1888  }//end getTaxableItemStringKeywordReplacement()
1889 
1890 
1898  {
1899  return $this->attr('currency_sign');
1900 
1901  }//end getTaxableItemStringKeywordReplacement()
1902 
1903 
1911  {
1912  return array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'TRANSACTION', '');
1913 
1914  }//end getTransactionNumberKeywordReplacement()
1915 
1916 
1924  {
1925  return array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'STATUS', '');
1926 
1927  }//end getTransactionStatusKeywordReplacement()
1928 
1929 
1937  {
1938  return array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'TYPE', '');
1939 
1940  }//end getTransactionTypeKeywordReplacement()
1941 
1942 
1950  {
1951  return array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'TIME', '');
1952 
1953  }//end getTransactionTimeKeywordReplacement()
1954 
1955 
1963  {
1964  $amount = array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'AMOUNT', '');
1965  return $this->_formatPriceAmount($amount);
1966 
1967  }//end getTransactionAmountKeywordReplacement()
1968 
1969 
1977  {
1978  return array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'CARDNO', '');
1979 
1980  }//end getTransactionCardNumberKeywordReplacement()
1981 
1982 
1990  {
1991  return array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'BILLING_NAME', '');
1992 
1993  }//end getTransactionBillingNameKeywordReplacement()
1994 
1995 
2003  {
2004  return array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'BILLING_ADDR', '');
2005 
2006  }//end getTransactionBillingAddressKeywordReplacement()
2007 
2008 
2016  {
2017  return array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'DELIVERY_NAME', '');
2018 
2019  }//end getTransactionDeliveryNameKeywordReplacement()
2020 
2021 
2029  {
2030  return array_get_index($this->_tmp['GATEWAY_RESPONSE'], 'DELIVERY_ADDR', '');
2031 
2032  }//end getTransactionDeliveryAddressKeywordReplacement()
2033 
2034 
2042  {
2043  $order = $this->getCurrentOrderAsset();
2044  if (is_null($order)) return;
2045 
2046  return $order->id;
2047 
2048  }//end getOrderNumberKeywordReplacement()
2049 
2050 
2058  {
2059  if (!empty($this->order)) {
2060  $order =& $this->order;
2061  return $order;
2062  }
2063 
2064  $order_id = @$_SESSION[$this->getPrefix()]['order_id'];
2065  if (empty($order_id)) {
2066  $order = NULL;
2067  return $order;
2068  }
2069 
2070  $this->order =& $GLOBALS['SQ_SYSTEM']->am->getAsset($order_id);
2071  $order =& $this->order;
2072  return $order;
2073 
2074  }//end getCurrentOrderAsset()
2075 
2076 
2083  function _getAssetItems()
2084  {
2085  $assets_in_cart = @$_SESSION[$this->getPrefix()]['assets'];
2086  if (is_null($assets_in_cart)) {
2087  $assets_in_cart = Array();
2088  }
2089  return $assets_in_cart;
2090 
2091  }//end _getAssetItems()
2092 
2093 
2100  function _clearAssetItems()
2101  {
2102  $_SESSION[$this->getPrefix()]['assets'] = Array();
2103 
2104  }//end _clearAssetItems()
2105 
2106 
2116  function _addAssetItem($assetid, $quantity=1)
2117  {
2118  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
2119  if (is_null($asset)) return FALSE;
2120 
2121  if (!$this->_isPurchasableAsset($asset)) {
2122  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
2123  return FALSE;
2124  }
2125 
2126  // can only buy one of each item
2127  if ($this->_isPurchasableAssetQuantityAllowed($asset)) {
2128  if (!is_numeric($quantity) || $quantity <= 0) {
2129  $quantity = 1;
2130  }
2131  } else {
2132  $quantity = 1;
2133  }
2134 
2135  $_SESSION[$this->getPrefix()]['assets'] = Array();
2136  $_SESSION[$this->getPrefix()]['assets'][$assetid] = $quantity;
2137 
2138  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
2139 
2140  return TRUE;
2141 
2142  }//end _addAssetItem()
2143 
2144 
2152  {
2153  $promo_codes_in_cart = @$_SESSION[$this->getPrefix()]['promo_code_assets'];
2154  if (is_null($promo_codes_in_cart)) {
2155  $promo_codes_in_cart = Array();
2156  }
2157 
2158  return $promo_codes_in_cart;
2159 
2160  }//end _getAssetItemPromotionalCodes()
2161 
2162 
2170  {
2171  $_SESSION[$this->getPrefix()]['promo_code_assets'] = Array();
2172 
2173  }//end _clearAssetItemPromotionalCodes()
2174 
2175 
2185  function _addAssetItemPromotionalCode($assetid, $promo_code)
2186  {
2187  if (trim($promo_code) == '') return;
2188 
2189  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
2190  if (is_null($asset)) return;
2191 
2192  if (!$this->_isPurchasableAssetPromotable($asset)) {
2193  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
2194  return;
2195  }
2196 
2197  $promo_code_asset = $this->_getPromotionalCodeAsset($asset, $promo_code);
2198 
2199  if (!is_null($promo_code_asset)){
2200  // Reset the promo code asset list because _addAssetItem() method also reset the asset list
2201  // A new array 'promo_code_assets' is created instead of using the 'assets' array
2202  // because we might want to add the promotional code for the whole ecommerce form later (the whole cart, not only individual items)
2203  $_SESSION[$this->getPrefix()]['promo_code_assets'] = Array();
2204  $_SESSION[$this->getPrefix()]['promo_code_assets'][$assetid] = $promo_code_asset->id;
2205  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($promo_code_asset);
2206  }
2207 
2208  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
2209 
2210  }//end _addAssetItemPromotionalCode()
2211 
2212 
2223  function _getPromotionalCodeDiscount($promo_code_assetid, $price, $quantity)
2224  {
2225  $promo_code_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($promo_code_assetid);
2226  $asset_data = Array('price' => $price, 'quantity' => $quantity);
2227 
2228  $promo_code_asset->process($asset_data);
2229 
2230  return $asset_data['discount'];
2231 
2232  }//end _getPromotionalCodeDiscount()
2233 
2234 
2241  function _getTotal()
2242  {
2243  $total = 0;
2244 
2245  if (isset($_SESSION[$this->getPrefix()]['order']['total'])) {
2246  $total = $_SESSION[$this->getPrefix()]['order']['total'];
2247  }
2248  return $total;
2249 
2250  }//end _getTotal()
2251 
2252 
2260  {
2261  $total_discount = 0;
2262 
2263  if (isset($_SESSION[$this->getPrefix()]['order']['total_discount'])) {
2264  $total_discount = $_SESSION[$this->getPrefix()]['order']['total_discount'];
2265  }
2266 
2267  return $total_discount;
2268 
2269  }//end _getTotalDiscount()
2270 
2271 
2280  function _getTaxableTotal()
2281  {
2282  $taxable_total = 0;
2283 
2284  if (isset($_SESSION[$this->getPrefix()]['order']['taxable_total'])) {
2285  $taxable_total = $_SESSION[$this->getPrefix()]['order']['taxable_total'];
2286  }
2287  return $taxable_total;
2288 
2289  }//end _getTaxableTotal()
2290 
2291 
2298  function _getTaxRate()
2299  {
2300  return $this->attr('tax_value');
2301 
2302  }//end _getTaxRate()
2303 
2304 
2311  function _getTaxTotal()
2312  {
2313  $taxable_total = $this->_getTaxableTotal();
2314 
2315  $tax_rate = $this->_getTaxRate();
2316  $total_tax = $taxable_total * $tax_rate/(100 + $tax_rate);
2317 
2318  return $total_tax;
2319 
2320  }//end _getTaxTotal()
2321 
2322 
2329  function _getOrderItems()
2330  {
2331 
2332  $items = @$_SESSION[$this->getPrefix()]['order']['items'];
2333  if (is_null($items) || !is_array($items)) {
2334  $items = Array();
2335  }
2336 
2337  return $items;
2338 
2339  }//end _getOrderItems()
2340 
2341 
2350  function _getPurchasableAssetPrice(&$asset)
2351  {
2352  $price_string = $this->attr('asset_price_source');
2353  $price = $asset->replaceKeywordsInString($price_string);
2354 
2355  if (!is_numeric($price)) $price = 0;
2356 
2357  return $price;
2358 
2359  }//end _getPurchasableAssetPrice()
2360 
2361 
2370  function _getPurchasableAssetName(&$asset)
2371  {
2372  $name_string = $this->attr('asset_name_source');
2373  $name = $asset->replaceKeywordsInString($name_string);
2374 
2375  if ($name == '') {
2376  $name = $asset->replaceKeywordsInString('%asset_name%');
2377  }
2378 
2379  return $name;
2380 
2381  }//end _getPurchasableAssetName()
2382 
2383 
2391  {
2392  $key_val_arr = Array();
2393  $var_rules = $this->attr('key_val_rules');
2394  if (empty($var_rules)) {
2395  return $key_val_arr;
2396  }
2397 
2398  $questions =& $this->getAllQuestionAssets();
2399  foreach ($questions as $q_id => $question) {
2400  if (key_exists($q_id, $var_rules)) {
2401  $var_rule = $var_rules[$q_id];
2402  $key = array_get_index($var_rule, 'key', '');
2403  if (trim($key) == '') {
2404  continue;
2405  }
2406 
2407  $val = '';
2408  if (!($question instanceof Form_Question_Type_Country) && $question->isSelection()) {
2409  $options = array_get_index($var_rule, 'value', Array());
2410  foreach ($options as $option_id => $option_val) {
2411  //if option is selcted and option is not --leave empty--
2412  if ($question->isSelected($option_id) && (!($question instanceof Form_question_type_select) || !$question->isEmptyOption($option_id))) {
2413  $val = $option_val;
2414  break;
2415  }
2416  }
2417  } else {
2418  $val = $this->current_answers[$q_id];
2419  }
2420 
2421  $key_val_arr[$key] = $val;
2422  }//end if
2423  }//end for
2424 
2425  return $key_val_arr;
2426 
2427  }//end _getPassThroughVars()
2428 
2429 
2438  function _isPurchasableAsset(&$asset)
2439  {
2440  $price_string = $this->attr('asset_price_source');
2441  $price = $asset->replaceKeywordsInString($price_string);
2442 
2443  return is_numeric($price);
2444 
2445  }//end _isPurchasableAsset()
2446 
2447 
2456  function _isPurchasableAssetTaxable(&$asset)
2457  {
2458  $tax_source_string = $this->attr('asset_taxable_source');
2459  $tax_check_string = $asset->replaceKeywordsInString($tax_source_string);
2460 
2461  return $tax_check_string !== '';
2462 
2463  }//end _isPurchasableAssetTaxable()
2464 
2465 
2475  {
2476  $multiple_source_string = $this->attr('asset_multiple_source');
2477  $check_string = $asset->replaceKeywordsInString($multiple_source_string);
2478 
2479  return $check_string !== '';
2480 
2481  }//end _isPurchasableAssetQuantityAllowed()
2482 
2483 
2493  {
2494  $promotable_source_string = $this->attr('asset_promotable_source');
2495  $check_string = $asset->replaceKeywordsInString($promotable_source_string);
2496 
2497  return (boolean) $check_string;
2498 
2499  }//end _isPurchasableAssetPromotable()
2500 
2501 
2511  function _getPromotionalCodeAsset(&$asset, $promo_code)
2512  {
2513  $am = $GLOBALS['SQ_SYSTEM']->am;
2514  $links = $am->getLinks($asset->id, SQ_LINK_NOTICE, 'promotional_code', TRUE, 'minor', $promo_code);
2515 
2516  foreach ($links as $link) {
2517  $promo_code_asset = $am->getAsset($link['majorid']);
2518  if (!is_null($promo_code_asset) && ($promo_code_asset->status == SQ_STATUS_LIVE)) {
2519  return $promo_code_asset;
2520  }
2521  }
2522 
2523  return NULL;
2524 
2525  }//end _getPromotionalCodeAsset()
2526 
2527 
2536  function _formatPriceAmount($amount=0)
2537  {
2538  return sprintf('%01.2f', $amount);
2539 
2540  }//end _formatPriceAmount()
2541 
2542 
2551  function _isItemTaxable($item_id)
2552  {
2553 
2554  $taxable = @$_SESSION[$this->getPrefix()]['order']['taxable_items'][$item_id];
2555  return !is_null($taxable);
2556 
2557  }//end _isItemTaxable()
2558 
2559 
2566  function _getLogFileName()
2567  {
2568  return 'order.log';
2569 
2570  }//end _getLogFileName()
2571 
2572 
2580  function _getLogFilePath()
2581  {
2582  return $this->data_path.'/'.$this->_getLogFileName();
2583 
2584  }//end _getLogFilePath()
2585 
2586 
2595  function _log($string='')
2596  {
2597  $file = $this->_getLogFilePath();
2598  if (!$file_pointer = fopen($file, 'a')) return FALSE;
2599 
2600  $sucess = fputs($file_pointer, $string);
2601  fclose($file_pointer);
2602  if ($sucess === FALSE) {
2603  trigger_error('Unable to write '.$file, E_USER_WARNING);
2604  return FALSE;
2605  }
2606 
2607  $om = umask(0000);
2608  chmod($file, 0664);
2609  umask($om);
2610 
2611  return TRUE;
2612 
2613  }//end _log()
2614 
2615 
2616 }//end class
2617 
2618 ?>