Skip to content
Snippets Groups Projects
Commit 3c4b9a85 authored by mattwire's avatar mattwire
Browse files

Drupal Webform: Re-enable hook_civicrm_buildForm and comment in different...

Drupal Webform: Re-enable hook_civicrm_buildForm and comment in different situations we need alterContent and buildForm to load js scripts
parent 52efe677
No related branches found
No related tags found
No related merge requests found
...@@ -879,10 +879,12 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment { ...@@ -879,10 +879,12 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
* @param array $errors * @param array $errors
*/ */
public function validatePaymentInstrument($values, &$errors) { public function validatePaymentInstrument($values, &$errors) {
CRM_Core_Form::validateMandatoryFields($this->getMandatoryFields(), $values, $errors); // Use $_POST here and not $values - for webform fields are not set in $values, but are in $_POST
CRM_Core_Form::validateMandatoryFields($this->getMandatoryFields(), $_POST, $errors);
if ($this->_paymentProcessor['payment_type'] == 1) { if ($this->_paymentProcessor['payment_type'] == 1) {
// Don't validate credit card details as they are not passed (and stripe does this for us) // Don't validate credit card details as they are not passed (and stripe does this for us)
//CRM_Core_Payment_Form::validateCreditCard($values, $errors, $this->_paymentProcessor['id']); //CRM_Core_Payment_Form::validateCreditCard($values, $errors, $this->_paymentProcessor['id']);
} }
} }
} }
...@@ -70,7 +70,9 @@ rgburton, Swingline0, BorislavZlatanov, agh1, & jmcclelland ...@@ -70,7 +70,9 @@ rgburton, Swingline0, BorislavZlatanov, agh1, & jmcclelland
TESTING TESTING
-------- --------
1. Test webform submission with payment and user-select, single processor. 1. Test webform submission with payment and user-select, single processor.
2. Test online contribution page with single processor, multi-processor (stripe default, stripe non-default). 1. Test online contribution page with single processor, multi-processor (stripe default, stripe non-default).
3. Test offline contribution page with single processor, multi-processor (stripe default, stripe non-default). 1. Test offline contribution page with single processor, multi-processor (stripe default, stripe non-default).
4. Test event registration. 1. Test event registration.
5. Test event registration (cart checkout). 1. Test event registration (cart checkout).
1. Test offline event registration.
1. Test offline membership.
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
*/ */
(function($, CRM) { (function($, CRM) {
var buttonText;
// Response from Stripe.createToken. // Response from Stripe.createToken.
function stripeResponseHandler(status, response) { function stripeResponseHandler(status, response) {
$form = getBillingForm(); $form = getBillingForm();
...@@ -18,7 +16,7 @@ ...@@ -18,7 +16,7 @@
$(".messages.crm-error.stripe-message").slideUp(); $(".messages.crm-error.stripe-message").slideUp();
$(".messages.crm-error.stripe-message:first").remove(); $(".messages.crm-error.stripe-message:first").remove();
} }
$form.prepend('<div class="messages crm-error stripe-message">' $form.prepend('<div class="messages alert alert-block alert-danger error crm-error stripe-message">'
+ '<strong>Payment Error Response:</strong>' + '<strong>Payment Error Response:</strong>'
+ '<ul id="errorList">' + '<ul id="errorList">'
+ '<li>Error: ' + response.error.message + '</li>' + '<li>Error: ' + response.error.message + '</li>'
...@@ -26,7 +24,7 @@ ...@@ -26,7 +24,7 @@
+ '</div>'); + '</div>');
$form.data('submitted', false); $form.data('submitted', false);
$submit.prop('disabled', false).attr('value', buttonText); $submit.prop('disabled', false);
} }
else { else {
var token = response['id']; var token = response['id'];
...@@ -75,27 +73,52 @@ ...@@ -75,27 +73,52 @@
return; return;
} }
$submit = getBillingSubmit(); $submit = getBillingSubmit();
// If another submit button on the form is pressed (eg. apply discount)
// add a flag that we can set to stop payment submission
$form.data('submit-dont-process', '0');
// Find submit buttons which should not submit payment
$form.find('[type="submit"][formnovalidate="1"], ' +
'[type="submit"][formnovalidate="formnovalidate"], ' +
'[type="submit"].cancel, ' +
'[type="submit"].webform-previous').click( function() {
debugging('adding submit-dont-process');
$form.data('submit-dont-process', 1);
});
$submit.click( function() {
debugging('clearing submit-dont-process');
$form.data('submit-dont-process', 0);
});
// Add a keypress handler to set flag if enter is pressed
$form.find('input#discountcode').keypress( function(e) {
if (e.which === 13) {
$form.data('submit-dont-process', 1);
}
});
var isWebform = getIsWebform(); var isWebform = getIsWebform();
// For CiviCRM Webforms. // For CiviCRM Webforms.
if (isWebform) { if (isWebform) {
// We need the action field for back/submit to work and redirect properly after submission
if (!($('#action').length)) { if (!($('#action').length)) {
$form.append('<input type="hidden" name="op" id="action" />'); $form.append($('<input type="hidden" name="op" id="action" />'));
} }
$(document).keypress(function(event) { var $actions = $form.find('[type=submit]');
$('[type=submit]').click(function() {
$('#action').val(this.value);
});
// If enter pressed, use our submit function
$form.keypress(function(event) {
if (event.which === 13) { if (event.which === 13) {
// Enter was pressed $('#action').val(this.value);
event.preventDefault();
submit(event); submit(event);
} }
}); });
$(":submit").click(function() {
$('#action').val(this.value);
});
$('#billingcheckbox:input').hide(); $('#billingcheckbox:input').hide();
$('label[for="billingcheckbox"]').hide(); $('label[for="billingcheckbox"]').hide();
var webformPrevious = $('input.webform-previous').first().val();
} }
else { else {
// As we use credit_card_number to pass token, make sure it is empty when shown // As we use credit_card_number to pass token, make sure it is empty when shown
...@@ -103,32 +126,21 @@ ...@@ -103,32 +126,21 @@
$form.find("input#cvv2").val(''); $form.find("input#cvv2").val('');
} }
$submit.removeAttr('onclick');
$form.unbind('submit');
// Intercept form submission. // Intercept form submission.
$form.on('submit', function(event) { $form.on('submit', function(event) {
submit(event); submit(event);
}); });
function submit(event) { function submit(event) {
event.preventDefault(); event.preventDefault();
debugging('submit handler');
$form = getBillingForm();
if ($form.data('submitted') === true) { if ($form.data('submitted') === true) {
// Previously submitted - don't submit again debugging('form already submitted');
alert('Form already submitted. Please wait.'); return false;
return true;
} else {
// Mark it so that the next submit can be ignored
// ADDED requirement that form be valid
if($form.valid()) {
$form.data('submitted', true);
}
} }
$submit = getBillingSubmit(); $form = getBillingForm();
var isWebform = getIsWebform();
// Don't handle submits generated by non-stripe processors // Don't handle submits generated by non-stripe processors
if (!$('input#stripe-pub-key').length) { if (!$('input#stripe-pub-key').length) {
...@@ -136,20 +148,21 @@ ...@@ -136,20 +148,21 @@
return true; return true;
} }
// Don't handle submits generated by the CiviDiscount button. // Don't handle submits generated by the CiviDiscount button.
if ($form.data('submit-dont-process') === 1) { if ($form.data('submit-dont-process')) {
debugging('Discount is in play'); debugging('non-payment submit detected - not submitting payment');
$form.get(0).submit();
return true; return true;
} }
$submit = getBillingSubmit();
var isWebform = getIsWebform();
if (isWebform) { if (isWebform) {
var $processorFields = $('.civicrm-enabled[name$="civicrm_1_contribution_1_contribution_payment_processor_id]"]'); var $processorFields = $('.civicrm-enabled[name$="civicrm_1_contribution_1_contribution_payment_processor_id]"]');
if ($('#action').attr('value') === webformPrevious) { $totalElement = $('#wf-crm-billing-total');
// Don't submit if the webform back button was pressed if ($totalElement.length) {
debugging('webform back button'); if ($totalElement.data('data-amount') === '0') {
return true;
}
if ($('#wf-crm-billing-total').length) {
if ($('#wf-crm-billing-total').data('data-amount') === '0') {
debugging('webform total is 0'); debugging('webform total is 0');
return true; return true;
} }
...@@ -161,9 +174,22 @@ ...@@ -161,9 +174,22 @@
} }
} }
} }
// Disable the submit button to prevent repeated clicks, cache button text, restore if Stripe returns error
buttonText = $submit.attr('value'); // Lock to prevent multiple submissions
$submit.prop('disabled', true).attr('value', 'Processing'); if ($form.data('submitted') === true) {
// Previously submitted - don't submit again
alert('Form already submitted. Please wait.');
return true;
} else {
// Mark it so that the next submit can be ignored
// ADDED requirement that form be valid
if($form.valid()) {
$form.data('submitted', true);
}
}
// Disable the submit button to prevent repeated clicks
$submit.prop('disabled', true);
// Handle multiple payment options and Stripe not being chosen. // Handle multiple payment options and Stripe not being chosen.
if ($form.find(".crm-section.payment_processor-section").length > 0) { if ($form.find(".crm-section.payment_processor-section").length > 0) {
...@@ -206,16 +232,11 @@ ...@@ -206,16 +232,11 @@
} }
function getIsWebform() { function getIsWebform() {
if ($('.webform-client-form').length) { return $('.webform-client-form').length;
return true;
}
else {
return false;
}
} }
function getBillingForm() { function getBillingForm() {
return CRM.$('input#stripe-pub-key').closest('form'); return $('input#stripe-pub-key').closest('form');
} }
function getBillingSubmit() { function getBillingSubmit() {
...@@ -223,24 +244,10 @@ ...@@ -223,24 +244,10 @@
var isWebform = getIsWebform(); var isWebform = getIsWebform();
if (isWebform) { if (isWebform) {
$submit = $form.find('.button-primary'); $submit = $form.find('[type="submit"].webform-submit');
} }
else { else {
$submit = $form.find('input[type="submit"].validate'); $submit = $form.find('[type="submit"].validate');
// If another submit button on the form is pressed (eg. apply discount)
// add a flag that we can set to stop payment submission
$form.data('submit-dont-process', '0');
// Find submit buttons with formnovalidate=1 and add an onclick handler to set flag
$form.find('input[type="submit"][formnovalidate="1"], input[type="submit"].cancel').click( function() {
$form.data('submit-dont-process', 1);
});
// Add a keypress handler to set flag if enter is pressed
$form.find('input#discountcode').keypress( function(e) {
if (e.which === 13) {
$form.data('submit-dont-process', 1);
}
});
} }
return $submit; return $submit;
} }
......
...@@ -188,16 +188,56 @@ function stripe_civicrm_managed(&$entities) { ...@@ -188,16 +188,56 @@ function stripe_civicrm_managed(&$entities) {
} }
} }
// Flag so we don't add the stripe scripts more than once.
static $_stripe_scripts_added;
/**
* Implementation of hook_civicrm_alterContent
*
* Adding civicrm_stripe.js in a way that works for webforms and (some) Civi forms.
* hook_civicrm_buildForm is not called for webforms
*
* @return void
*/
function stripe_civicrm_alterContent( &$content, $context, $tplName, &$object ) {
global $_stripe_scripts_added;
/* Adding stripe js:
* - Webforms don't get scripts added by hook_civicrm_buildForm so we have to user alterContent
* - (Webforms still call buildForm and it looks like they are added but they are not,
* which is why we check for $object instanceof CRM_Financial_Form_Payment here to ensure that
* Webforms always have scripts added).
* - Almost all forms have context = 'form' and a paymentprocessor object.
* - Membership backend form is a 'page' and has a _isPaymentProcessor=true flag.
*
*/
if (($context == 'form' && !empty($object->_paymentProcessor['class_name']))
|| (($context == 'page') && !empty($object->_isPaymentProcessor))) {
if (!$_stripe_scripts_added || $object instanceof CRM_Financial_Form_Payment) {
$stripeJSURL = CRM_Core_Resources::singleton()
->getUrl('com.drastikbydesign.stripe', 'js/civicrm_stripe.js');
$content .= "<script src='{$stripeJSURL}'></script>";
$content .= "<script src='https://js.stripe.com/v2/'></script>";
$_stripe_scripts_added = TRUE;
}
}
}
/** /**
* Add stripe.js to forms, to generate stripe token * Add stripe.js to forms, to generate stripe token
* hook_civicrm_alterContent is not called for all forms (eg. CRM_Contribute_Form_Contribution on backend)
* @param $formName * @param $formName
* @param $form * @param $form
*/ */
function stripe_civicrm_buildForm($formName, &$form) { function stripe_civicrm_buildForm($formName, &$form) {
global $_stripe_scripts_added;
if (!empty($form->_paymentProcessor['class_name'])) { if (!empty($form->_paymentProcessor['class_name'])) {
// civicrm_stripe.js is not included on backend form renewal unless we add it here. if (!$_stripe_scripts_added) {
CRM_Core_Resources::singleton()->addScriptUrl('https://js.stripe.com/v2/', 10, 'page-body'); CRM_Core_Resources::singleton()
CRM_Core_Resources::singleton()->addScriptFile('com.drastikbydesign.stripe', 'js/civicrm_stripe.js'); ->addScriptUrl('https://js.stripe.com/v2/', 10, 'page-body');
CRM_Core_Resources::singleton()
->addScriptFile('com.drastikbydesign.stripe', 'js/civicrm_stripe.js');
}
$_stripe_scripts_added = TRUE;
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment