diff --git a/CRM/Twingle/Tools.php b/CRM/Twingle/Tools.php
new file mode 100644
index 0000000..6af1999
--- /dev/null
+++ b/CRM/Twingle/Tools.php
@@ -0,0 +1,94 @@
+ 'trxn_id,contribution_status_id,payment_instrument_id',
+ 'id' => $recurring_contribution_id]);
+
+ // check if this is a SEPA transaction
+ //if (self::isSDD($recurring_contribution['payment_instrument_id'])) return;
+
+ // check if it's really a termination (i.e. current status is 2 or 5)
+ if (!in_array($recurring_contribution['contribution_status_id'], [2,5])) return;
+
+ // check if it's a Twingle contribution
+ if (substr($recurring_contribution['trxn_id'], 0, strlen($prefix)) == $prefix) {
+ // this is a Twingle contribution that is about to be terminated
+ throw new Exception(E::ts("This is a Twingle recurring contribution. It should be terminated through the Twingle interface, otherwise it will still be collected."));
+ }
+ }
+
+ /**
+ * Check if the given payment instrument is SEPA
+ *
+ * @param $payment_instrument_id string payment instrument
+ * @return boolean
+ */
+ public static function isSDD($payment_instrument_id) {
+ static $sepa_payment_instruments = NULL;
+ if ($sepa_payment_instruments === NULL) {
+ // init with instrument names
+ $sepa_payment_instruments = ['FRST', 'RCUR', 'OOFF'];
+
+ // lookup and add instrument IDs
+ $lookup = civicrm_api3('OptionValue', 'get', [
+ 'option_group_id' => 'payment_instrument',
+ 'name' => ['IN' => $sepa_payment_instruments],
+ 'return' => 'value'
+ ]);
+ foreach ($lookup['values'] as $payment_instrument) {
+ $sepa_payment_instruments[] = $payment_instrument['value'];
+ }
+ }
+ return in_array($payment_instrument_id, $sepa_payment_instruments);
+ }
+}
diff --git a/api/v3/TwingleDonation/Cancel.php b/api/v3/TwingleDonation/Cancel.php
index 00fc6a8..4883217 100644
--- a/api/v3/TwingleDonation/Cancel.php
+++ b/api/v3/TwingleDonation/Cancel.php
@@ -122,12 +122,14 @@ function civicrm_api3_twingle_donation_Cancel($params) {
));
}
else {
+ CRM_Twingle_Tools::$protection_suspended = TRUE;
$contribution = civicrm_api3($contribution_type, 'create', array(
'id' => $contribution['id'],
'cancel_date' => $params['cancelled_at'],
'contribution_status_id' => 'Cancelled',
'cancel_reason' => $params['cancel_reason'],
));
+ CRM_Twingle_Tools::$protection_suspended = FALSE;
}
$result = civicrm_api3_create_success($contribution);
diff --git a/api/v3/TwingleDonation/Endrecurring.php b/api/v3/TwingleDonation/Endrecurring.php
index baecb32..aa5d967 100644
--- a/api/v3/TwingleDonation/Endrecurring.php
+++ b/api/v3/TwingleDonation/Endrecurring.php
@@ -113,11 +113,13 @@ function civicrm_api3_twingle_donation_endrecurring($params) {
));
}
else {
+ CRM_Twingle_Tools::$protection_suspended = TRUE;
$contribution = civicrm_api3('ContributionRecur', 'create', array(
'id' => $contribution['id'],
'end_date' => $params['ended_at'],
'contribution_status_id' => CRM_Twingle_Submission::CONTRIBUTION_STATUS_COMPLETED,
));
+ CRM_Twingle_Tools::$protection_suspended = FALSE;
}
$result = civicrm_api3_create_success($contribution);
diff --git a/settings/twingle.setting.php b/settings/twingle.setting.php
index 1df4d27..d703845 100644
--- a/settings/twingle.setting.php
+++ b/settings/twingle.setting.php
@@ -31,6 +31,20 @@ return array(
'is_contact' => 0,
'description' => 'Whether to provide CiviSEPA functionality for manual debit payment method. This requires the CiviSEPA (org.project60.sepa) extension be installed.',
),
+ 'twingle_protect_recurring' => array(
+ 'group_name' => 'de.systopia.twingle',
+ 'group' => 'de.systopia.twingle',
+ 'name' => 'twingle_protect_recurring',
+ 'type' => 'Boolean',
+ 'quick_form_type' => 'YesNo',
+ 'html_type' => 'radio',
+ 'title' => 'Protect Recurring Contributions',
+ 'default' => 0,
+ 'add' => '4.6',
+ 'is_domain' => 1,
+ 'is_contact' => 0,
+ 'description' => 'Will protect all recurring contributions created by Twingle from termination, since this does NOT terminate the Twingle collection process. Currently only works with a prefix',
+ ),
'twingle_prefix' => array(
'group_name' => 'de.systopia.twingle',
'group' => 'de.systopia.twingle',
diff --git a/templates/CRM/Twingle/Form/Settings.hlp b/templates/CRM/Twingle/Form/Settings.hlp
index b9ff9d1..8b5ef1b 100644
--- a/templates/CRM/Twingle/Form/Settings.hlp
+++ b/templates/CRM/Twingle/Form/Settings.hlp
@@ -16,6 +16,10 @@
{ts domain="de.systopia.twingle" 1="CiviSEPA (org.project60.sepa) extension"}When the %1 is enabled and one of its payment instruments is assigned to a Twingle payment method (practically the debit_manual payment method), submitting a Twingle donation through the API will create a SEPA mandate with the given data.{/ts}
{/htxt}
+{htxt id='id-twingle_protect_recurring'}
+ {ts domain="de.systopia.twingle"}Will protect all recurring contributions created by Twingle from termination, since this does NOT terminate the Twingle collection process{/ts}
+{/htxt}
+
{htxt id='id-twingle_prefix'}
{ts domain="de.systopia.twingle"}You can use this setting to add a prefix to the Twingle transaction ID, in order to avoid collisions with other transaction ids.{/ts}
{/htxt}
diff --git a/twingle.php b/twingle.php
index c2a064e..214d041 100644
--- a/twingle.php
+++ b/twingle.php
@@ -3,6 +3,15 @@
require_once 'twingle.civix.php';
use CRM_Twingle_ExtensionUtil as E;
+/**
+ * Implements hook_civicrm_pre().
+ */
+function twingle_civicrm_pre($op, $objectName, $id, &$params) {
+ if ($objectName == 'ContributionRecur' && $op == 'edit') {
+ CRM_Twingle_Tools::checkRecurringContributionChange($id, $params);
+ }
+}
+
/**
* Implements hook_civicrm_config().
*