*/
/**
- *
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2015
*/
class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form {
/**
- * The recurring contribution id, used when editing the recurring contribution
+ * The recurring contribution id, used when editing the recurring contribution.
*
* @var int
*/
- protected $_crid = NULL;
+ protected $contributionRecurID = NULL;
protected $_coid = NULL;
public $_paymentProcessorObj = NULL;
+ /**
+ * Fields that affect the schedule and are defined as editable by the processor.
+ *
+ * @var array
+ */
+ protected $editableScheduleFields = array();
+
/**
* The id of the contact associated with this recurring contribution.
*
*/
public function preProcess() {
- $this->_crid = CRM_Utils_Request::retrieve('crid', 'Integer', $this, FALSE);
- if ($this->_crid) {
- $this->_paymentProcessor = CRM_Contribute_BAO_ContributionRecur::getPaymentProcessor($this->_crid);
+ $this->contributionRecurID = CRM_Utils_Request::retrieve('crid', 'Integer', $this, FALSE);
+ if ($this->contributionRecurID) {
+ $this->_paymentProcessor = CRM_Contribute_BAO_ContributionRecur::getPaymentProcessor($this->contributionRecurID);
+ if (!$this->_paymentProcessor) {
+ CRM_Core_Error::statusBounce(ts('There is no valid processor for this subscription so it cannot be edited.'));
+ }
$this->_paymentProcessorObj = $this->_paymentProcessor['object'];
- $this->_subscriptionDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($this->_crid);
+ $this->_subscriptionDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($this->contributionRecurID);
}
$this->_coid = CRM_Utils_Request::retrieve('coid', 'Integer', $this, FALSE);
$this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($this->_coid, 'contribute', 'info');
$this->_paymentProcessorObj = CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($this->_coid, 'contribute', 'obj');
$this->_subscriptionDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($this->_coid, 'contribution');
- $this->_crid = $this->_subscriptionDetails->recur_id;
+ $this->contributionRecurID = $this->_subscriptionDetails->recur_id;
}
- elseif ($this->_crid) {
- $this->_coid = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->_crid, 'id', 'contribution_recur_id');
+ elseif ($this->contributionRecurID) {
+ $this->_coid = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->contributionRecurID, 'id', 'contribution_recur_id');
}
- if ((!$this->_crid) ||
+ if ((!$this->contributionRecurID) ||
($this->_subscriptionDetails == CRM_Core_DAO::$_nullObject)
) {
CRM_Core_Error::fatal('Required information missing.');
}
$this->assign('self_service', $this->_selfService);
- if (!$this->_paymentProcessorObj->isSupported('changeSubscriptionAmount')) {
- $userAlert = ts('Updates made using this form will change the recurring contribution information stored in your CiviCRM database, but will NOT be sent to the payment processor. You must enter the same changes using the payment processor web site.');
- CRM_Core_Session::setStatus($userAlert, ts('Warning'), 'alert');
+ $this->editableScheduleFields = $this->_paymentProcessorObj->getEditableRecurringScheduleFields();
+
+ $changeHelpText = $this->_paymentProcessorObj->getRecurringScheduleUpdateHelpText();
+ if (!in_array('amount', $this->editableScheduleFields)) {
+ // Not sure if this is good behaviour - maintaining this existing behaviour for now.
+ CRM_Core_Session::setStatus($changeHelpText, ts('Warning'), 'alert');
+ }
+ else {
+ $this->assign('changeHelpText', $changeHelpText);
+ }
+ $alreadyHardCodedFields = array('amount', 'installments');
+ foreach ($this->editableScheduleFields as $editableScheduleField) {
+ if (!in_array($editableScheduleField, $alreadyHardCodedFields)) {
+ $this->addField($editableScheduleField, array(
+ 'entity' => 'ContributionRecur',
+ 'context' => $this->getDefaultContext(),
+ ));
+ }
}
- $this->assign('isChangeSupported', $this->_paymentProcessorObj->isSupported('changeSubscriptionAmount'));
+ $this->assign('editableScheduleFields', array_diff($this->editableScheduleFields, $alreadyHardCodedFields));
$this->assign('paymentProcessor', $this->_paymentProcessor);
$this->assign('frequency_unit', $this->_subscriptionDetails->frequency_unit);
$this->assign('frequency_interval', $this->_subscriptionDetails->frequency_interval);
CRM_Utils_System::setTitle(ts('Update Recurring Contribution'));
- // handle context redirection
+ // Handle context redirection.
CRM_Contribute_BAO_ContributionRecur::setSubscriptionContext();
}
* Note that in edit/view mode the default values are retrieved from the database.
*/
public function setDefaultValues() {
-
$this->_defaults = array();
$this->_defaults['amount'] = $this->_subscriptionDetails->amount;
$this->_defaults['installments'] = $this->_subscriptionDetails->installments;
$this->_defaults['campaign_id'] = $this->_subscriptionDetails->campaign_id;
$this->_defaults['financial_type_id'] = $this->_subscriptionDetails->financial_type_id;
$this->_defaults['is_notify'] = 1;
+ foreach ($this->editableScheduleFields as $field) {
+ $this->_defaults[$field] = $this->_subscriptionDetails->$field;
+ }
return $this->_defaults;
}
CRM_Campaign_BAO_Campaign::addCampaign($this);
}
- if (CRM_Contribute_BAO_ContributionRecur::supportsFinancialTypeChange($this->_crid)) {
+ if (CRM_Contribute_BAO_ContributionRecur::supportsFinancialTypeChange($this->contributionRecurID)) {
$this->addEntityRef('financial_type_id', ts('Financial Type'), array('entity' => 'FinancialType'), TRUE);
}
}
}
+ /**
+ * Explicitly declare the form context.
+ */
+ public function getDefaultContext() {
+ return 'create';
+ }
+
}
return $this->_paymentProcessor['payment_type'] == 1 ? $this->getCreditCardFormFields() : $this->getDirectDebitFormFields();
}
+ /**
+ * Get an array of the fields that can be edited on the recurring contribution.
+ *
+ * Some payment processors support editing the amount and other scheduling details of recurring payments, especially
+ * those which use tokens. Others are fixed. This function allows the processor to return an array of the fields that
+ * can be updated from the contribution recur edit screen.
+ *
+ * The fields are likely to be a subset of these
+ * - 'amount',
+ * - 'installments',
+ * - 'frequency_interval',
+ * - 'frequency_unit',
+ * - 'cycle_day',
+ * - 'next_sched_contribution_date',
+ * - 'end_date',
+ * - 'failure_retry_day',
+ *
+ * The form does not restrict which fields from the contribution_recur table can be added (although if the html_type
+ * metadata is not defined in the xml for the field it will cause an error.
+ *
+ * Open question - would it make sense to return membership_id in this - which is sometimes editable and is on that
+ * form (UpdateSubscription).
+ *
+ * @return array
+ */
+ public function getEditableRecurringScheduleFields() {
+ if (method_exists($this, 'changeSubscriptionAmount')) {
+ return array('amount');
+ }
+ }
+
+ /**
+ * Get the help text to present on the recurring update page.
+ *
+ * This should reflect what can or cannot be edited.
+ *
+ * @return string
+ */
+ public function getRecurringScheduleUpdateHelpText() {
+ if (!in_array('amount', $this->getEditableRecurringScheduleFields())) {
+ return ts('Updates made using this form will change the recurring contribution information stored in your CiviCRM database, but will NOT be sent to the payment processor. You must enter the same changes using the payment processor web site.');
+ }
+ return ts('Use this form to change the amount or number of installments for this recurring contribution. Changes will be automatically sent to the payment processor. You can not change the contribution frequency.');
+ }
+
/**
* Get the metadata for all required fields.
*
+--------------------------------------------------------------------+
*}
<div class="crm-block crm-form-block crm-recurcontrib-form-block">
- {if $isChangeSupported}
+ {if $changeHelpText}
<div class="help">
- {ts}Use this form to change the amount or number of installments for this recurring contribution. Changes will be automatically sent to the payment processor. You can not change the contribution frequency.{/ts}
+ {$changeHelpText}
</div>
{/if}
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
</tr>
<tr><td class="label">{$form.installments.label}</td><td>{$form.installments.html}<br />
<span class="description">{ts}Total number of payments to be made. Set this to 0 if this is an open-ended commitment i.e. no set end date.{/ts}</span></td></tr>
+ {foreach from=$editableScheduleFields item='field'}
+ <tr><td class="label">{$form.$field.label}</td><td>{$form.$field.html}</td></tr>
+ {/foreach}
{if !$self_service}
<tr><td class="label">{$form.is_notify.label}</td><td>{$form.is_notify.html}</td></tr>
<tr><td class="label">{$form.campaign_id.label}</td><td>{$form.campaign_id.html}</td></tr>
<tr><td class="label">{$form.financial_type_id.label}</td><td>{$form.financial_type_id.html}</td></tr>
{/if}
-
- {* Currently changes to interval, unit and cycle day are not supported. *}
- {*
- <tr><td class="label">{$form.frequency_interval.label}</td><td>{$form.frequency_interval.html}<br />
- <span class="description">{ts}Number of time units for recurrence of payment.{/ts}</span></td></tr>
- <tr><td class="label">{$form.frequency_unit.label}</td><td>{$form.frequency_unit.html}<br />
- <span class="description">{ts}Time unit for recurrence of payment. For example, "month".{/ts}</span></td></tr>
- <tr><td class="label">{$form.cycle_day.label}</td><td>{$form.cycle_day.html}<br />
- <span class="description">{ts}Day in the period when the payment should be charged.{/ts}</span></td></tr>
- *}
</table>
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
<required>true</required>
<comment>Amount to be contributed or charged each recurrence.</comment>
<add>1.6</add>
+ <html>
+ <type>Text</type>
+ </html>
</field>
<field>
<name>currency</name>
<required>true</required>
<comment>Number of time units for recurrence of payment.</comment>
<add>1.6</add>
+ <html>
+ <type>Text</type>
+ </html>
</field>
<field>
<name>installments</name>
<type>int unsigned</type>
<comment>Total number of payments to be made. Set this to 0 if this is an open-ended commitment i.e. no set end date.</comment>
<add>1.6</add>
+ <html>
+ <type>Text</type>
+ </html>
</field>
<field>
<name>start_date</name>
<required>true</required>
<comment>The date the first scheduled recurring contribution occurs.</comment>
<add>1.6</add>
+ <html>
+ <type>Select Date</type>
+ </html>
</field>
<field>
<name>create_date</name>
<required>true</required>
<comment>When this recurring contribution record was created.</comment>
<add>1.6</add>
+ <html>
+ <type>Select Date</type>
+ </html>
</field>
<field>
<name>modified_date</name>
<type>datetime</type>
<comment>Last updated date for this record. mostly the last time a payment was received</comment>
<add>1.6</add>
+ <html>
+ <type>Select Date</type>
+ </html>
</field>
<field>
<name>cancel_date</name>
<type>datetime</type>
<comment>Date this recurring contribution was cancelled by contributor- if we can get access to it</comment>
<add>1.6</add>
+ <html>
+ <type>Select Date</type>
+ </html>
</field>
<field>
<name>end_date</name>
<type>datetime</type>
<comment>Date this recurring contribution finished successfully</comment>
<add>1.6</add>
+ <html>
+ <type>Select Date</type>
+ </html>
</field>
<field>
<name>processor_id</name>
<type>datetime</type>
<comment>Next scheduled date</comment>
<add>4.4</add>
+ <html>
+ <type>Select Date</type>
+ </html>
</field>
<field>
<name>failure_count</name>
<title>Retry Failed Attempt Date</title>
<comment>Date to retry failed attempt</comment>
<add>1.6</add>
+ <html>
+ <type>Select Date</type>
+ </html>
</field>
<field>
<name>auto_renew</name>