From 5ad7069abc2ff6c36e15558ea9bfb768af2e721e Mon Sep 17 00:00:00 2001 From: Marc Michalsky Date: Mon, 29 Jun 2020 16:41:45 +0200 Subject: [PATCH] implement Double-Opt-In --- CRM/Twingle/Form/Profile.php | 7 ++ CRM/Twingle/Profile.php | 2 + README.md | 17 +++ api/v3/TwingleDonation/Doubleoptinconfirm.php | 115 ++++++++++++++++++ api/v3/TwingleDonation/Submit.php | 22 +++- l10n/de_DE/LC_MESSAGES/twingle.po | 4 + templates/CRM/Twingle/Form/Profile.tpl | 5 + twingle.php | 1 + 8 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 api/v3/TwingleDonation/Doubleoptinconfirm.php diff --git a/CRM/Twingle/Form/Profile.php b/CRM/Twingle/Form/Profile.php index a38dc7e..7038470 100644 --- a/CRM/Twingle/Form/Profile.php +++ b/CRM/Twingle/Form/Profile.php @@ -336,6 +336,13 @@ class CRM_Twingle_Form_Profile extends CRM_Core_Form { array('class' => 'crm-select2 huge', 'multiple' => 'multiple') ); + $this->add( + 'checkbox', // field type + 'double_opt_in', // field name + E::ts('Use Twingle\'s Double-Opt-In procedure'), // field label + FALSE // is not required + ); + $this->add( 'select', // field type 'postinfo_groups', // field name diff --git a/CRM/Twingle/Profile.php b/CRM/Twingle/Profile.php index be93bc6..e0afe35 100644 --- a/CRM/Twingle/Profile.php +++ b/CRM/Twingle/Profile.php @@ -221,6 +221,7 @@ class CRM_Twingle_Profile { 'membership_type_id', 'membership_type_id_recur', 'membership_postprocess_call', + 'double_opt_in' ), // Add payment methods. array_keys(static::paymentInstruments()), @@ -293,6 +294,7 @@ class CRM_Twingle_Profile { 'custom_field_mapping' => NULL, 'membership_type_id' => NULL, 'membership_type_id_recur' => NULL, + 'double_opt_in' => NULL, ) // Add contribution status for all payment methods. + array_fill_keys(array_map(function($attribute) { diff --git a/README.md b/README.md index e8c2a1d..16ce32e 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ for all newly created Twingle projects. | CiviSEPA creditor | When enabled to integrate with CiviSEPA, specify the CiviSEPA creditor to use. | | Gender options | Specify which CiviCRM gender option the incoming Twingle gender value should be mapped to. The list is based on your CiviCRM configuration. | | Record *Payment method* as | Specifiy the payment methods mapping for incoming donations for each Twingle payment method. | +| Double-Opt-In | Group membership for newsletter mailing lists will be pending until receivement of confirming API call. Usage in combination with activated Double-Opt-In in Twingle manager. | | Sign up for groups | Whenever the donor checked the newsletter/postal mailing/donation receipt checkbox on the Twingle form, the contact will be added to the groups listed here. | | Assign donation to campaign | The donation will be assigned to the selected campaign. If a campaign ID is being submitted using the `campaign_id` parameter, this setting will be overridden with the submitted value. | | Create membership of type | A membership of the selected type will be created for the Individual contact for incoming one-time donations. If no membership type is selected, no membership will be created. | @@ -148,3 +149,19 @@ The action accepts the following parameters: You may also refer to [the code](https://github.com/systopia/de.systopia.twingle/blob/master/api/v3/TwingleDonation/Cancel.php) for more insight into this API action. + +### Double-Opt-In confirmation + +- Entity: `TwingleDonation` +- Action: `doubleoptinconfirm` + +The action accepts the following parameters: + +| Parameter | Type | Description | Values/Format | Required | +|------------------------------|--------|----------------------------------------------------|-------------------------------------------------------|----------| +| `project_id` | String | The Twingle project ID | | Yes | +| `user_email` | String | The e-mail address of the contact | A valid e-mail address | Yes | + +You may also refer to +[the code](https://github.com/systopia/de.systopia.twingle/blob/master/api/v3/TwingleDonation/Doubleoptinconfirm.php) +for more insight into this API action. \ No newline at end of file diff --git a/api/v3/TwingleDonation/Doubleoptinconfirm.php b/api/v3/TwingleDonation/Doubleoptinconfirm.php new file mode 100644 index 0000000..bc5f70b --- /dev/null +++ b/api/v3/TwingleDonation/Doubleoptinconfirm.php @@ -0,0 +1,115 @@ + 'project_id', + 'title' => E::ts('Project ID'), + 'type' => CRM_Utils_Type::T_STRING, + 'api.required' => 1, + 'description' => E::ts('The Twingle project ID.'), + ); + $params['user_email'] = array( + 'name' => 'user_email', + 'title' => E::ts('Email address'), + 'type' => CRM_Utils_Type::T_STRING, + 'api.required' => 1, + 'description' => E::ts('The e-mail address of the contact.') + ); +} + +/** + * TwingleDonation.Cancel API + * + * @param array $params + * @return array API result descriptor + * @see civicrm_api3_create_success + * @see civicrm_api3_create_error + */ +function civicrm_api3_twingle_donation_DoubleOptInConfirm($params) +{ + // Log call if debugging is enabled within civicrm.settings.php. + if (defined('TWINGLE_API_LOGGING') && TWINGLE_API_LOGGING) { + CRM_Core_Error::debug_log_message('TwingleDonation.DoubleOptInConfirm: ' . json_encode($params, JSON_PRETTY_PRINT)); + } + + try { + // Get the profile defined for the given form ID, or the default profile + // if none matches. + $profile = CRM_Twingle_Profile::getProfileForProject($params['project_id']); + + // Get the newsletter groups defined in the profile + $newsletter_groups = $profile->getAttribute('newsletter_groups'); + + // Extract user email from API call + if (!empty($params['user_email'])) { + $contacts = civicrm_api3('Email', 'get', array( + 'seqential' => 1, + 'email' => $params['user_email'], + )); + + // Get pending group memberships for user + if (!empty($contacts['values'])) { + foreach ($contacts['values'] as $contact) { + $groups = civicrm_api3('GroupContact', 'get', array( + 'sequential' => 1, + 'contact_id' => $contact['contact_id'], + 'status' => "Pending", + )); + + // Only in newsletter groups: change group membership from pending to added + if (!empty($groups['values'])) { + foreach ($groups['values'] as $group) { + if (in_array($group['group_id'], $newsletter_groups)) { + civicrm_api3('GroupContact', 'create', array( + 'group_id' => $group['group_id'], + 'contact_id' => $contact['contact_id'], + 'status' => "Added", + $result_values['groups'][] = $group['group_id'], + )); + // Display message if group membership was confirmed correctly + $result_values['double_opt_in'][$group['group_id']] = "Subscription confirmed"; + } + } + // Display message if there is no pending group membership + } else { + $result_values['double_opt_in'][] = "Could not confirm subscription: No pending group membership"; + } + } + // Display message if email can't be found + } else { + $result_values['double_opt_in'][] = "Could not confirm subscription: Email not found"; + } + } + $result = civicrm_api3_create_success($result_values); + } catch (Exception $exception) { + $result = civicrm_api3_create_error($exception->getMessage()); + } + + return $result; +} diff --git a/api/v3/TwingleDonation/Submit.php b/api/v3/TwingleDonation/Submit.php index afa3ca3..96f00af 100644 --- a/api/v3/TwingleDonation/Submit.php +++ b/api/v3/TwingleDonation/Submit.php @@ -484,8 +484,28 @@ function civicrm_api3_twingle_donation_Submit($params) { $result_values['organization'] = $organisation_id; } + // If Twingle's Double-Opt-In procedure is used, add contact with status "pending" to the newsletter groups + // defined in the profile + if (!empty($profile->getAttribute('double_opt_in')) && + !empty($params['newsletter']) && + !empty($groups = $profile->getAttribute('newsletter_groups'))) { + foreach ($groups as $group_id) { + if (empty(civicrm_api3('GroupContact', 'get', array( + 'group_id' => $group_id, + 'contact_id' => $contact_id, + ))['values'])) { + civicrm_api3('GroupContact', 'create', array( + 'group_id' => $group_id, + 'contact_id' => $contact_id, + 'status' => "Pending", + )); + $result_values['double_opt_in'][] = "Pending"; + } + $result_values['newsletter'][] = $group_id; + } + // If requested, add contact to newsletter groups defined in the profile. - if (!empty($params['newsletter']) && !empty($groups = $profile->getAttribute('newsletter_groups'))) { + } elseif (!empty($params['newsletter']) && !empty($groups = $profile->getAttribute('newsletter_groups'))) { foreach ($groups as $group_id) { civicrm_api3('GroupContact', 'create', array( 'group_id' => $group_id, diff --git a/l10n/de_DE/LC_MESSAGES/twingle.po b/l10n/de_DE/LC_MESSAGES/twingle.po index f914552..2662754 100644 --- a/l10n/de_DE/LC_MESSAGES/twingle.po +++ b/l10n/de_DE/LC_MESSAGES/twingle.po @@ -306,3 +306,7 @@ msgstr "Profil %1 zurücksetzen" #: templates/CRM/Twingle/Page/Profiles.tpl msgid "Delete profile %1" msgstr "Profil % 1 löschen" + +#: templates/CRM/Twingle/Page/Profiles.tpl +msgid "Use Twingle's Double-Opt-In procedure" +msgstr "Nutze Twingles Double-Opt-In-Verfahren" diff --git a/templates/CRM/Twingle/Form/Profile.tpl b/templates/CRM/Twingle/Form/Profile.tpl index 708cb5a..3e6a07e 100644 --- a/templates/CRM/Twingle/Form/Profile.tpl +++ b/templates/CRM/Twingle/Form/Profile.tpl @@ -208,6 +208,11 @@ + + + + + diff --git a/twingle.php b/twingle.php index 214d041..d18e45e 100644 --- a/twingle.php +++ b/twingle.php @@ -151,6 +151,7 @@ function twingle_civicrm_alterAPIPermissions($entity, $action, &$params, &$permi $permissions['twingle_donation']['submit'] = array('access Twingle API'); $permissions['twingle_donation']['cancel'] = array('access Twingle API'); $permissions['twingle_donation']['endrecurring'] = array('access Twingle API'); + $permissions['twingle_donation']['doubleoptinconfirm'] = array('access Twingle API'); } // --- Functions below this ship commented out. Uncomment as required. ---
{$form.double_opt_in.label}{$form.double_opt_in.html}
{$form.newsletter_groups.label} {$form.newsletter_groups.html}