Skip to content

Commit 56f192e

Browse files
authored
Merge pull request #20210 from eileenmcnaughton/cancel
Fix old-ish regression on paypal standard self-service cancel links
2 parents eee12f8 + 2d852c6 commit 56f192e

File tree

5 files changed

+166
-13
lines changed

5 files changed

+166
-13
lines changed

CRM/Contribute/Page/Tab.php

+81
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,87 @@ public static function recurLinks(int $recurID, $context = 'contribution') {
9494
return $links;
9595
}
9696

97+
/**
98+
* Get the recur links to return for self service.
99+
*
100+
* These are the links to present to a logged in user wishing
101+
* to service their own
102+
*
103+
* @param int $recurID
104+
*
105+
* @return array|array[]
106+
* @throws \CRM_Core_Exception
107+
* @throws \CiviCRM_API3_Exception
108+
*/
109+
public static function selfServiceRecurLinks(int $recurID): array {
110+
$links = [];
111+
$paymentProcessorObj = Civi\Payment\System::singleton()->getById(CRM_Contribute_BAO_ContributionRecur::getPaymentProcessorID($recurID));
112+
if ($paymentProcessorObj->supports('cancelRecurring')
113+
&& $paymentProcessorObj->subscriptionURL($recurID, 'recur', 'cancel')
114+
) {
115+
$url = $paymentProcessorObj->subscriptionURL($recurID, 'recur', 'cancel');
116+
$links[CRM_Core_Action::DISABLE] = [
117+
'url' => $url,
118+
'name' => ts('Cancel'),
119+
'title' => ts('Cancel'),
120+
// Only display on-site links in a popup.
121+
'class' => (stripos($url, 'http') !== FALSE) ? 'no-popup' : '',
122+
];
123+
}
124+
125+
if ($paymentProcessorObj->supports('UpdateSubscriptionBillingInfo')
126+
&& $paymentProcessorObj->subscriptionURL($recurID, 'recur', 'billing')
127+
) {
128+
$url = $paymentProcessorObj->subscriptionURL($recurID, 'recur', 'billing');
129+
$links[CRM_Core_Action::RENEW] = [
130+
'name' => ts('Change Billing Details'),
131+
'title' => ts('Change Billing Details'),
132+
'url' => $url,
133+
// Only display on-site links in a popup.
134+
'class' => (stripos($url, 'http') !== FALSE) ? 'no-popup' : '',
135+
];
136+
}
137+
138+
if (($paymentProcessorObj->supports('ChangeSubscriptionAmount')
139+
|| $paymentProcessorObj->supports('EditRecurringContribution'))
140+
&& $paymentProcessorObj->subscriptionURL($recurID, 'recur', 'update')
141+
) {
142+
$url = $paymentProcessorObj->subscriptionURL($recurID, 'recur', 'update');
143+
$links[CRM_Core_Action::UPDATE] = [
144+
'name' => ts('Edit'),
145+
'title' => ts('Edit Recurring Payment'),
146+
'url' => $url,
147+
// Only display on-site links in a popup.
148+
'class' => (stripos($url, 'http') !== FALSE) ? 'no-popup' : '',
149+
];
150+
}
151+
return $links;
152+
}
153+
154+
/**
155+
* Get recurring links appropriate to viewing a user dashboard.
156+
*
157+
* A contact should be able to see links appropriate to them (e.g
158+
* payment processor cancel page) if viewing their own dashboard and
159+
* links appropriate to the contact they are viewing, if they have
160+
* permission, if viewing another user.
161+
*
162+
* @param int $recurID
163+
* @param int $contactID
164+
*
165+
* @return array|array[]
166+
* @throws \CRM_Core_Exception
167+
* @throws \CiviCRM_API3_Exception
168+
*/
169+
public static function dashboardRecurLinks(int $recurID, int $contactID): array {
170+
$links = [];
171+
if ($contactID && $contactID === CRM_Core_Session::getLoggedInContactID()) {
172+
$links = self::selfServiceRecurLinks($recurID);
173+
}
174+
$links += self::recurLinks($recurID, 'dashboard');
175+
return $links;
176+
}
177+
97178
/**
98179
* called when action is browse.
99180
*

CRM/Contribute/Page/UserDashboard.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public function listContribution() {
9898
$values['recur_status'] = $recurStatus[$values['contribution_status_id']];
9999
$recurRow[$values['id']] = $values;
100100

101-
$action = array_sum(array_keys(CRM_Contribute_Page_Tab::recurLinks((int) $recur->id, 'dashboard')));
101+
$action = array_sum(array_keys(CRM_Contribute_Page_Tab::dashboardRecurLinks((int) $recur->id, (int) $recur->contact_id)));
102102

103103
$details = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($recur->id, 'recur');
104104
$hideUpdate = $details->membership_id & $details->auto_renew;
@@ -107,7 +107,7 @@ public function listContribution() {
107107
$action -= CRM_Core_Action::UPDATE;
108108
}
109109

110-
$recurRow[$values['id']]['action'] = CRM_Core_Action::formLink(CRM_Contribute_Page_Tab::recurLinks((int) $recur->id, 'dashboard'),
110+
$recurRow[$values['id']]['action'] = CRM_Core_Action::formLink(CRM_Contribute_Page_Tab::dashboardRecurLinks((int) $recur->id, (int) $this->_contactId),
111111
$action, [
112112
'cid' => $this->_contactId,
113113
'crid' => $values['id'],

CRM/Core/Session.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ public static function getLoggedInContactID() {
563563
if (!is_numeric($session->get('userID'))) {
564564
return NULL;
565565
}
566-
return $session->get('userID');
566+
return (int) $session->get('userID');
567567
}
568568

569569
/**

CRM/Member/Page/RecurringContributions.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ private function setActionsForRecurringContribution(int $recurID, &$recurringCon
125125
}
126126

127127
$recurringContribution['action'] = CRM_Core_Action::formLink(
128-
CRM_Contribute_Page_Tab::recurLinks($recurID, 'contribution'),
128+
CRM_Contribute_Page_Tab::recurLinks($recurID),
129129
$action,
130130
[
131131
'cid' => $this->contactID,

tests/phpunit/CRM/Contribute/Page/TabTest.php

+81-9
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,79 @@
1818
*/
1919
class CRM_Contribute_Page_TabTest extends CiviUnitTestCase {
2020

21+
/**
22+
* Clean up after test.
23+
*
24+
* @throws \CRM_Core_Exception
25+
*/
26+
public function tearDown(): void {
27+
$this->quickCleanUpFinancialEntities();
28+
parent::tearDown();
29+
}
30+
2131
/**
2232
* Test links render correctly for manual processor.
2333
*
2434
* @throws \API_Exception
2535
* @throws \CiviCRM_API3_Exception
2636
*/
27-
public function testLinks() {
28-
$contactID = $this->individualCreate();
29-
$recurID = ContributionRecur::create()->setValues([
37+
public function testLinksManual(): void {
38+
[$contactID, $recurID] = $this->setupTemplate();
39+
40+
$templateVariable = CRM_Core_Smarty::singleton()->get_template_vars();
41+
$this->assertEquals('Mr. Anthony Anderson II', $templateVariable['displayName']);
42+
$this->assertEquals("<span><a href=\"/index.php?q=civicrm/contact/view/contributionrecur&amp;reset=1&amp;id=" . $recurID . "&amp;cid=" . $contactID . "&amp;context=contribution\" class=\"action-item crm-hover-button\" title='View Recurring Payment' >View</a><a href=\"/index.php?q=civicrm/contribute/updaterecur&amp;reset=1&amp;action=update&amp;crid=1&amp;cid=3&amp;context=contribution\" class=\"action-item crm-hover-button\" title='Edit Recurring Payment' >Edit</a><a href=\"/index.php?q=civicrm/contribute/unsubscribe&amp;reset=1&amp;crid=" . $recurID . "&amp;cid=" . $contactID . "&amp;context=contribution\" class=\"action-item crm-hover-button\" title='Cancel' >Cancel</a></span>",
43+
$this->getActionHtml()
44+
);
45+
}
46+
47+
/**
48+
* Test links render correctly for manual processor.
49+
*
50+
* @throws \API_Exception
51+
* @throws \CiviCRM_API3_Exception
52+
*/
53+
public function testLinksPaypalStandard(): void {
54+
$this->setupTemplate([
55+
'payment_processor_id' => $this->paymentProcessorCreate(['payment_processor_type_id' => 'PayPal_Standard']),
56+
'contact_id' => $this->createLoggedInUser(),
57+
]);
58+
$expected = '<span><a href="/index.php?q=civicrm/contact/view/contributionrecur&amp;reset=1&amp;id=1&amp;cid=3&amp;context=contribution" class="action-item crm-hover-button" title=\'View Recurring Payment\' >View</a><a href="/index.php?q=civicrm/contribute/updaterecur&amp;reset=1&amp;action=update&amp;crid=1&amp;cid=3&amp;context=contribution" class="action-item crm-hover-button" title=\'Edit Recurring Payment\' >Edit</a></span><span class=\'btn-slide crm-hover-button\'>more<ul class=\'panel\'><li><a href="/index.php?q=civicrm/contribute/unsubscribe&amp;reset=1&amp;crid=1&amp;cid=3&amp;context=contribution" class="action-item crm-hover-button" title=\'Cancel\' >Cancel</a></li><li><a href="/index.php?q=civicrm/contribute/updatebilling&amp;reset=1&amp;crid=1&amp;cid=3&amp;context=contribution" class="action-item crm-hover-button" title=\'Change Billing Details\' >Change Billing Details</a></li></ul></span>';
59+
$this->assertEquals($expected, $this->getActionHtml());
60+
61+
$page = new CRM_Contribute_Page_UserDashboard();
62+
$page->run();
63+
$expected = '<span><a href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_subscr-find&alias=sunil._1183377782_biz_api1.webaccess.co.in" class="action-item crm-hover-button no-popup" title=\'Cancel\' >Cancel</a>'
64+
. '<a href="/index.php?q=civicrm/contact/view/contributionrecur&amp;reset=1&amp;id=1&amp;cid=3&amp;context=dashboard" class="action-item crm-hover-button" title=\'View Recurring Payment\' >View</a>'
65+
. '</span><span class=\'btn-slide crm-hover-button\'>more<ul class=\'panel\'><li><a href="/index.php?q=civicrm/contribute/updaterecur&amp;reset=1&amp;action=update&amp;crid=1&amp;cid=3&amp;context=dashboard" class="action-item crm-hover-button" title=\'Edit Recurring Payment\' >Edit</a></li><li><a href="/index.php?q=civicrm/contribute/updatebilling&amp;reset=1&amp;crid=1&amp;cid=3&amp;context=dashboard" class="action-item crm-hover-button" title=\'Change Billing Details\' >Change Billing Details</a></li></ul></span>';
66+
$this->assertEquals(
67+
$expected,
68+
$this->getDashboardActionHtml()
69+
);
70+
}
71+
72+
/**
73+
* Set up template for user dashboard.
74+
*
75+
* Create the recurring contribution, contribution and run the dashboard.
76+
*
77+
* @param array $recurParams
78+
*
79+
* @return array
80+
* @throws \API_Exception
81+
* @throws \CiviCRM_API3_Exception
82+
* @throws \Civi\API\Exception\UnauthorizedException
83+
*/
84+
protected function setupTemplate($recurParams = []): array {
85+
$contactID = $recurParams['contact_id'] ?? $this->individualCreate();
86+
$recurID = ContributionRecur::create()->setValues(array_merge([
3087
'contact_id' => $contactID,
3188
'amount' => 10,
3289
'frequency_interval' => 'week',
3390
'start_date' => 'now',
3491
'is_active' => TRUE,
3592
'contribution_status_id:name' => 'Pending',
36-
])
93+
], $recurParams))
3794
->addChain(
3895
'contribution',
3996
Contribution::create()->setValues([
@@ -48,12 +105,27 @@ public function testLinks() {
48105
$page->_contactId = $contactID;
49106
$page->_action = CRM_Core_Action::VIEW;
50107
$page->browse();
108+
return [$contactID, $recurID];
109+
}
51110

52-
$templateVariable = CRM_Core_Smarty::singleton()->get_template_vars();
53-
$this->assertEquals('Mr. Anthony Anderson II', $templateVariable['displayName']);
54-
$this->assertEquals("<span><a href=\"/index.php?q=civicrm/contact/view/contributionrecur&amp;reset=1&amp;id=" . $recurID . "&amp;cid=" . $contactID . "&amp;context=contribution\" class=\"action-item crm-hover-button\" title='View Recurring Payment' >View</a><a href=\"/index.php?q=civicrm/contribute/updaterecur&amp;reset=1&amp;action=update&amp;crid=1&amp;cid=3&amp;context=contribution\" class=\"action-item crm-hover-button\" title='Edit Recurring Payment' >Edit</a><a href=\"/index.php?q=civicrm/contribute/unsubscribe&amp;reset=1&amp;crid=" . $recurID . "&amp;cid=" . $contactID . "&amp;context=contribution\" class=\"action-item crm-hover-button\" title='Cancel' >Cancel</a></span>",
55-
$templateVariable['activeRecurRows'][1]['action']
56-
);
111+
/**
112+
* Get the html assigned as actions.
113+
*
114+
* @return string
115+
*/
116+
protected function getActionHtml(): string {
117+
return CRM_Core_Smarty::singleton()
118+
->get_template_vars()['activeRecurRows'][1]['action'];
119+
}
120+
121+
/**
122+
* Get the html assigned as actions.
123+
*
124+
* @return string
125+
*/
126+
protected function getDashboardActionHtml(): string {
127+
return CRM_Core_Smarty::singleton()
128+
->get_template_vars()['recurRows'][1]['action'];
57129
}
58130

59131
}

0 commit comments

Comments
 (0)