3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
30 * @copyright CiviCRM LLC (c) 2004-2015
34 * This class generates form components generic to recurring contributions.
36 * It delegates the work to lower level subclasses and integrates the changes
37 * back in. It also uses a lot of functionality with the CRM API's, so any change
38 * made here could potentially affect the API etc. Be careful, be aware, use unit tests.
40 class CRM_Contribute_Form_UpdateSubscription
extends CRM_Core_Form
{
43 * The recurring contribution id, used when editing the recurring contribution.
47 protected $contributionRecurID = NULL;
49 protected $_coid = NULL;
51 protected $_subscriptionDetails = NULL;
53 protected $_selfService = FALSE;
55 public $_paymentProcessor = NULL;
57 public $_paymentProcessorObj = NULL;
60 * Fields that affect the schedule and are defined as editable by the processor.
64 protected $editableScheduleFields = array();
67 * The id of the contact associated with this recurring contribution.
74 * Pre-processing for the form.
78 public function preProcess() {
80 $this->contributionRecurID
= CRM_Utils_Request
::retrieve('crid', 'Integer', $this, FALSE);
81 if ($this->contributionRecurID
) {
82 $this->_paymentProcessor
= CRM_Contribute_BAO_ContributionRecur
::getPaymentProcessor($this->contributionRecurID
);
83 if (!$this->_paymentProcessor
) {
84 CRM_Core_Error
::statusBounce(ts('There is no valid processor for this subscription so it cannot be edited.'));
86 $this->_paymentProcessorObj
= $this->_paymentProcessor
['object'];
87 $this->_subscriptionDetails
= CRM_Contribute_BAO_ContributionRecur
::getSubscriptionDetails($this->contributionRecurID
);
90 $this->_coid
= CRM_Utils_Request
::retrieve('coid', 'Integer', $this, FALSE);
92 $this->_paymentProcessor
= CRM_Financial_BAO_PaymentProcessor
::getProcessorForEntity($this->_coid
, 'contribute', 'info');
93 $this->_paymentProcessorObj
= CRM_Financial_BAO_PaymentProcessor
::getProcessorForEntity($this->_coid
, 'contribute', 'obj');
94 $this->_subscriptionDetails
= CRM_Contribute_BAO_ContributionRecur
::getSubscriptionDetails($this->_coid
, 'contribution');
95 $this->contributionRecurID
= $this->_subscriptionDetails
->recur_id
;
97 elseif ($this->contributionRecurID
) {
98 $this->_coid
= CRM_Core_DAO
::getFieldValue('CRM_Contribute_DAO_Contribution', $this->contributionRecurID
, 'id', 'contribution_recur_id');
101 if ((!$this->contributionRecurID
) ||
102 ($this->_subscriptionDetails
== CRM_Core_DAO
::$_nullObject)
104 CRM_Core_Error
::fatal('Required information missing.');
107 if ($this->_subscriptionDetails
->membership_id
&& $this->_subscriptionDetails
->auto_renew
) {
108 CRM_Core_Error
::fatal(ts('You cannot update the subscription.'));
111 if (!CRM_Core_Permission
::check('edit contributions')) {
112 $userChecksum = CRM_Utils_Request
::retrieve('cs', 'String', $this, FALSE);
113 if (!CRM_Contact_BAO_Contact_Utils
::validChecksum($this->_subscriptionDetails
->contact_id
, $userChecksum)) {
114 CRM_Core_Error
::fatal(ts('You do not have permission to update subscription.'));
116 $this->_selfService
= TRUE;
118 $this->assign('self_service', $this->_selfService
);
120 $this->editableScheduleFields
= $this->_paymentProcessorObj
->getEditableRecurringScheduleFields();
122 $changeHelpText = $this->_paymentProcessorObj
->getRecurringScheduleUpdateHelpText();
123 if (!in_array('amount', $this->editableScheduleFields
)) {
124 // Not sure if this is good behaviour - maintaining this existing behaviour for now.
125 CRM_Core_Session
::setStatus($changeHelpText, ts('Warning'), 'alert');
128 $this->assign('changeHelpText', $changeHelpText);
130 $alreadyHardCodedFields = array('amount', 'installments');
131 foreach ($this->editableScheduleFields
as $editableScheduleField) {
132 if (!in_array($editableScheduleField, $alreadyHardCodedFields)) {
133 $this->addField($editableScheduleField, array('entity' => 'ContributionRecur'));
137 $this->assign('editableScheduleFields', array_diff($this->editableScheduleFields
, $alreadyHardCodedFields));
138 $this->assign('paymentProcessor', $this->_paymentProcessor
);
139 $this->assign('frequency_unit', $this->_subscriptionDetails
->frequency_unit
);
140 $this->assign('frequency_interval', $this->_subscriptionDetails
->frequency_interval
);
142 if ($this->_subscriptionDetails
->contact_id
) {
143 list($this->_donorDisplayName
, $this->_donorEmail
) = CRM_Contact_BAO_Contact
::getContactDetails($this->_subscriptionDetails
->contact_id
);
146 CRM_Utils_System
::setTitle(ts('Update Recurring Contribution'));
148 // Handle context redirection.
149 CRM_Contribute_BAO_ContributionRecur
::setSubscriptionContext();
153 * Set default values for the form.
155 * Note that in edit/view mode the default values are retrieved from the database.
157 public function setDefaultValues() {
158 $this->_defaults
= array();
159 $this->_defaults
['amount'] = $this->_subscriptionDetails
->amount
;
160 $this->_defaults
['installments'] = $this->_subscriptionDetails
->installments
;
161 $this->_defaults
['campaign_id'] = $this->_subscriptionDetails
->campaign_id
;
162 $this->_defaults
['financial_type_id'] = $this->_subscriptionDetails
->financial_type_id
;
163 $this->_defaults
['is_notify'] = 1;
164 foreach ($this->editableScheduleFields
as $field) {
165 $this->_defaults
[$field] = $this->_subscriptionDetails
->$field;
168 return $this->_defaults
;
172 * Actually build the components of the form.
174 public function buildQuickForm() {
175 // CRM-16398: If current recurring contribution got > 1 lineitems then make amount field readonly
176 $amtAttr = array('size' => 20);
177 $lineItems = CRM_Price_BAO_LineItem
::getLineItemsByContributionID($this->_coid
);
178 if (count($lineItems) > 1) {
179 $amtAttr +
= array('readonly' => TRUE);
181 $this->addMoney('amount', ts('Recurring Contribution Amount'), TRUE, $amtAttr,
182 TRUE, 'currency', $this->_subscriptionDetails
->currency
, TRUE
185 $this->add('text', 'installments', ts('Number of Installments'), array('size' => 20), FALSE);
187 if ($this->_donorEmail
) {
188 $this->add('checkbox', 'is_notify', ts('Notify Contributor?'));
191 if (CRM_Core_Permission
::check('edit contributions')) {
192 CRM_Campaign_BAO_Campaign
::addCampaign($this, $this->_subscriptionDetails
->campaign_id
);
195 if (CRM_Contribute_BAO_ContributionRecur
::supportsFinancialTypeChange($this->contributionRecurID
)) {
196 $this->addEntityRef('financial_type_id', ts('Financial Type'), array('entity' => 'FinancialType'), TRUE);
200 if ($this->_selfService
) {
204 // define the buttons
205 $this->addButtons(array(
208 'name' => ts('Save'),
213 'name' => ts('Cancel'),
220 * Called after the user submits the form.
222 public function postProcess() {
223 // store the submitted values in an array
224 $params = $this->exportValues();
226 if ($this->_selfService
&& $this->_donorEmail
) {
227 // for self service force notify
228 $params['is_notify'] = 1;
231 // if this is an update of an existing recurring contribution, pass the ID
232 $params['id'] = $this->_subscriptionDetails
->recur_id
;
235 $params['subscriptionId'] = $this->_subscriptionDetails
->subscription_id
;
236 $updateSubscription = TRUE;
237 if ($this->_paymentProcessorObj
->isSupported('changeSubscriptionAmount')) {
238 $updateSubscription = $this->_paymentProcessorObj
->changeSubscriptionAmount($message, $params);
240 if (is_a($updateSubscription, 'CRM_Core_Error')) {
241 CRM_Core_Error
::displaySessionError($updateSubscription);
242 $status = ts('Could not update the Recurring contribution details');
243 $msgTitle = ts('Update Error');
246 elseif ($updateSubscription) {
248 $result = CRM_Contribute_BAO_ContributionRecur
::add($params);
249 $status = ts('Recurring contribution has been updated to: %1, every %2 %3(s) for %4 installments.',
251 1 => CRM_Utils_Money
::format($params['amount'], $this->_subscriptionDetails
->currency
),
252 2 => $this->_subscriptionDetails
->frequency_interval
,
253 3 => $this->_subscriptionDetails
->frequency_unit
,
254 4 => $params['installments'],
258 $msgTitle = ts('Update Success');
259 $msgType = 'success';
260 $msg = ts('Recurring Contribution Updated');
261 $contactID = $this->_subscriptionDetails
->contact_id
;
263 if ($this->_subscriptionDetails
->amount
!= $params['amount']) {
264 $message .= "<br /> " . ts("Recurring contribution amount has been updated from %1 to %2 for this subscription.",
266 1 => CRM_Utils_Money
::format($this->_subscriptionDetails
->amount
, $this->_subscriptionDetails
->currency
),
267 2 => CRM_Utils_Money
::format($params['amount'], $this->_subscriptionDetails
->currency
),
269 if ($this->_subscriptionDetails
->amount
< $params['amount']) {
270 $msg = ts('Recurring Contribution Updated - increased installment amount');
273 $msg = ts('Recurring Contribution Updated - decreased installment amount');
277 if ($this->_subscriptionDetails
->installments
!= $params['installments']) {
278 $message .= "<br /> " . ts("Recurring contribution installments have been updated from %1 to %2 for this subscription.", array(
279 1 => $this->_subscriptionDetails
->installments
,
280 2 => $params['installments'],
284 $activityParams = array(
285 'source_contact_id' => $contactID,
286 'activity_type_id' => CRM_Core_OptionGroup
::getValue('activity_type',
287 'Update Recurring Contribution',
291 'details' => $message,
292 'activity_date_time' => date('YmdHis'),
293 'status_id' => CRM_Core_OptionGroup
::getValue('activity_status',
298 $session = CRM_Core_Session
::singleton();
299 $cid = $session->get('userID');
302 $activityParams['target_contact_id'][] = $activityParams['source_contact_id'];
303 $activityParams['source_contact_id'] = $cid;
305 CRM_Activity_BAO_Activity
::create($activityParams);
307 if (!empty($params['is_notify'])) {
309 if ($this->_subscriptionDetails
->contribution_page_id
) {
310 CRM_Core_DAO
::commonRetrieveAll('CRM_Contribute_DAO_ContributionPage', 'id',
311 $this->_subscriptionDetails
->contribution_page_id
, $value, array(
314 'receipt_from_email',
317 $receiptFrom = '"' . CRM_Utils_Array
::value('receipt_from_name', $value[$this->_subscriptionDetails
->contribution_page_id
]) . '" <' . $value[$this->_subscriptionDetails
->contribution_page_id
]['receipt_from_email'] . '>';
320 $domainValues = CRM_Core_BAO_Domain
::getNameAndEmail();
321 $receiptFrom = "$domainValues[0] <$domainValues[1]>";
324 list($donorDisplayName, $donorEmail) = CRM_Contact_BAO_Contact
::getContactDetails($contactID);
327 'recur_frequency_interval' => $this->_subscriptionDetails
->frequency_interval
,
328 'recur_frequency_unit' => $this->_subscriptionDetails
->frequency_unit
,
329 'amount' => CRM_Utils_Money
::format($params['amount']),
330 'installments' => $params['installments'],
333 $tplParams['contact'] = array('display_name' => $donorDisplayName);
334 $tplParams['receipt_from_email'] = $receiptFrom;
336 $sendTemplateParams = array(
337 'groupName' => 'msg_tpl_workflow_contribution',
338 'valueName' => 'contribution_recurring_edit',
339 'contactId' => $contactID,
340 'tplParams' => $tplParams,
341 'isTest' => $this->_subscriptionDetails
->is_test
,
342 'PDFFilename' => 'receipt.pdf',
343 'from' => $receiptFrom,
344 'toName' => $donorDisplayName,
345 'toEmail' => $donorEmail,
347 list($sent) = CRM_Core_BAO_MessageTemplate
::sendTemplate($sendTemplateParams);
351 $session = CRM_Core_Session
::singleton();
352 $userID = $session->get('userID');
353 if ($userID && $status) {
354 CRM_Core_Session
::setStatus($status, $msgTitle, $msgType);
358 CRM_Utils_System
::setUFMessage($status);
360 // keep result as 1, since we not displaying anything on the redirected page anyway
361 return CRM_Utils_System
::redirect(CRM_Utils_System
::url('civicrm/contribute/subscriptionstatus',
362 "reset=1&task=update&result=1"));
367 * Explicitly declare the form context.
369 public function getDefaultContext() {