[WIP] twingleDonation.Submit API action and general profile functionality

This commit is contained in:
Jens Schuppe 2018-10-05 15:25:31 +02:00
parent 061972706c
commit e141f2951a
14 changed files with 1048 additions and 16 deletions

View file

@ -0,0 +1,402 @@
<?php
/*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*/
use CRM_Twingle_ExtensionUtil as E;
/**
* Form controller class
*
* @see https://wiki.civicrm.org/confluence/display/CRMDOC/QuickForm+Reference
*/
class CRM_Twingle_Form_Profile extends CRM_Core_Form {
/**
* @var CRM_Twingle_Profile $profile
*
* The profile object the form is acting on.
*/
protected $profile;
/**
* @var string
*
* The operation to perform within the form.
*/
protected $_op;
/**
* @var array
*
* A static cache of retrieved payment instruments found within
* self::getPaymentInstruments().
*/
protected static $_paymentInstruments = NULL;
/**
* Builds the form structure.
*/
public function buildQuickForm() {
// "Create" is the default operation.
if (!$this->_op = CRM_Utils_Request::retrieve('op', 'String', $this)) {
$this->_op = 'create';
}
// Verify that profile with the given name exists.
$profile_name = CRM_Utils_Request::retrieve('name', 'String', $this);
if (!$this->profile = CRM_Twingle_Profile::getProfile($profile_name)) {
$profile_name = NULL;
}
// Assign template variables.
$this->assign('op', $this->_op);
$this->assign('profile_name', $profile_name);
// Set redirect destination.
$this->controller->_destination = CRM_Utils_System::url('civicrm/admin/settings/twingle/profiles', 'reset=1');
switch ($this->_op) {
case 'delete':
if ($profile_name) {
CRM_Utils_System::setTitle(E::ts('Delete Twingle API profile <em>%1</em>', array(1 => $profile_name)));
$this->addButtons(array(
array(
'type' => 'submit',
'name' => ($profile_name == 'default' ? E::ts('Reset') : E::ts('Delete')),
'isDefault' => TRUE,
),
));
}
parent::buildQuickForm();
return;
case 'edit':
// When editing without a valid profile name, edit the default profile.
if (!$profile_name) {
$profile_name = 'default';
$this->profile = CRM_Twingle_Profile::getProfile($profile_name);
}
CRM_Utils_System::setTitle(E::ts('Edit Twingle API profile <em>%1</em>', array(1 => $this->profile->getName())));
break;
case 'create':
// Load factory default profile values.
$this->profile = CRM_twingle_Profile::createDefaultProfile($profile_name);
CRM_Utils_System::setTitle(E::ts('New Twingle API profile'));
break;
}
// Add form elements.
$is_default = $profile_name == 'default';
$this->add(
($is_default ? 'static' : 'text'),
'name',
E::ts('Profile name'),
array(),
!$is_default
);
$this->add(
'text', // field type
'selector', // field name
E::ts('Project IDs'), // field label
array(),
TRUE // is required
);
$this->add(
'select',
'location_type_id',
E::ts('Location type'),
$this->getLocationTypes(),
TRUE
);
$this->add(
'select', // field type
'financial_type_id', // field name
E::ts('Financial Type'), // field label
$this->getFinancialTypes(), // list of options
TRUE // is required
);
$payment_instruments = CRM_Twingle_Profile::paymentInstruments();
$this->assign('payment_instruments', $payment_instruments);
foreach ($payment_instruments as $pi_name => $pi_label) {
$this->add(
'select', // field type
$pi_name, // field name
E::ts('Record %1 as', array(1 => $pi_label)), // field label
$this->getPaymentInstruments(), // list of options
TRUE // is required
);
}
$this->add(
'select', // field type
'newsletter_groups', // field name
E::ts('Sign up for newsletter groups'), // field label
$this->getNewsletterGroups(), // list of options
FALSE, // is not required
array('class' => 'crm-select2 huge', 'multiple' => 'multiple')
);
$this->add(
'select', // field type
'postinfo_groups', // field name
E::ts('Sign up for postal mail groups'), // field label
$this->getPostinfoGroups(), // list of options
FALSE, // is not required
array('class' => 'crm-select2 huge', 'multiple' => 'multiple')
);
$this->add(
'select', // field type
'donation_receipt_groups', // field name
E::ts('Sign up for Donation receipt groups'), // field label
$this->getDonationReceiptGroups(), // list of options
FALSE, // is not required
array('class' => 'crm-select2 huge', 'multiple' => 'multiple')
);
$this->addButtons(array(
array(
'type' => 'submit',
'name' => E::ts('Save'),
'isDefault' => TRUE,
),
));
// Export form elements.
parent::buildQuickForm();
}
/**
* @inheritdoc
*/
public function addRules() {
$this->addFormRule(array('CRM_Twingle_Form_Profile', 'validateProfileForm'));
}
/**
* Validates the profile form.
*
* @param array $values
* The submitted form values, keyed by form element name.
*
* @return bool | array
* TRUE when the form was successfully validated, or an array of error
* messages, keyed by form element name.
*/
public static function validateProfileForm($values) {
$errors = array();
// Restrict profile names to alphanumeric characters and the underscore.
if (isset($values['name']) && preg_match("/[^A-Za-z0-9\_]/", $values['name'])) {
$errors['name'] = E::ts('Only alphanumeric characters and the underscore (_) are allowed for profile names.');
}
return empty($errors) ? TRUE : $errors;
}
/**
* Set the default values (i.e. the profile's current data) in the form.
*/
public function setDefaultValues() {
$defaults = parent::setDefaultValues();
if (in_array($this->_op, array('create', 'edit'))) {
$defaults['name'] = $this->profile->getName();
foreach ($this->profile->getData() as $element_name => $value) {
$defaults[$element_name] = $value;
}
}
return $defaults;
}
/**
* Store the values submitted with the form in the profile.
*/
public function postProcess() {
$values = $this->exportValues();
if (in_array($this->_op, array('create', 'edit'))) {
if (empty($values['name'])) {
$values['name'] = 'default';
}
$this->profile->setName($values['name']);
foreach ($this->profile->getData() as $element_name => $value) {
if (isset($values[$element_name])) {
$this->profile->setAttribute($element_name, $values[$element_name]);
}
}
$this->profile->saveProfile();
}
elseif ($this->_op == 'delete') {
$this->profile->deleteProfile();
}
parent::postProcess();
}
/**
* Retrieves location types present within the system as options for select
* form elements.
*/
public function getLocationTypes() {
$location_types = array();
$query = civicrm_api3('LocationType', 'get', array(
'is_active' => 1,
));
foreach ($query['values'] as $type) {
$location_types[$type['id']] = $type['name'];
}
return $location_types;
}
/**
* Retrieves financial types present within the system as options for select
* form elements.
*/
public function getFinancialTypes() {
$financial_types = array();
$query = civicrm_api3('FinancialType', 'get', array(
'is_active' => 1,
'option.limit' => 0,
'return' => 'id,name'
));
foreach ($query['values'] as $type) {
$financial_types[$type['id']] = $type['name'];
}
return $financial_types;
}
/**
* Retrieves campaigns present within the system as options for select form
* elements.
*/
public function getCampaigns() {
$campaigns = array('' => E::ts("no campaign"));
$query = civicrm_api3('Campaign', 'get', array(
'is_active' => 1,
'option.limit' => 0,
'return' => 'id,title'
));
foreach ($query['values'] as $campaign) {
$campaigns[$campaign['id']] = $campaign['title'];
}
return $campaigns;
}
/**
* Retrieves payment instruments present within the system as options for
* select form elements.
*/
public function getPaymentInstruments() {
if (!isset(self::$_paymentInstruments)) {
self::$_paymentInstruments = array();
$query = civicrm_api3('OptionValue', 'get', array(
'option_group_id' => 'payment_instrument',
'is_active' => 1,
'option.limit' => 0,
'return' => 'value,label'
));
foreach ($query['values'] as $payment_instrument) {
self::$_paymentInstruments[$payment_instrument['value']] = $payment_instrument['label'];
}
}
return self::$_paymentInstruments;
}
/**
* Retrieves active groups used as mailing lists within the system as options
* for select form elements.
*/
public function getNewsletterGroups() {
$groups = array();
$group_types = civicrm_api3('OptionValue', 'get', array(
'option_group_id' => 'group_type',
'name' => CRM_Twingle_Submission::GROUP_TYPE_NEWSLETTER,
));
if ($group_types['count'] > 0) {
$group_type = reset($group_types['values']);
$query = civicrm_api3('Group', 'get', array(
'is_active' => 1,
'group_type' => array('LIKE' => '%' . CRM_Utils_Array::implodePadded($group_type['value']) . '%'),
'option.limit' => 0,
'return' => 'id,name'
));
foreach ($query['values'] as $group) {
$groups[$group['id']] = $group['name'];
}
}
else {
$groups[''] = E::ts('No newsletter groups available');
}
return $groups;
}
/**
* Retrieves active groups used as postal mailing lists within the system as
* options for select form elements.
*/
public function getPostinfoGroups() {
$groups = array();
$group_types = civicrm_api3('OptionValue', 'get', array(
'option_group_id' => 'group_type',
'name' => CRM_Twingle_Submission::GROUP_TYPE_POSTINFO,
));
if ($group_types['count'] > 0) {
$group_type = reset($group_types['values']);
$query = civicrm_api3('Group', 'get', array(
'is_active' => 1,
'group_type' => array('LIKE' => '%' . CRM_Utils_Array::implodePadded($group_type['value']) . '%'),
'option.limit' => 0,
'return' => 'id,name'
));
foreach ($query['values'] as $group) {
$groups[$group['id']] = $group['name'];
}
}
else {
$groups[''] = E::ts('No postal mailing groups available');
}
return $groups;
}
/**
* Retrieves active groups used as donation receipt requester lists within the
* system as options for select form elements.
*/
public function getDonationReceiptGroups() {
$groups = array();
$group_types = civicrm_api3('OptionValue', 'get', array(
'option_group_id' => 'group_type',
'name' => CRM_Twingle_Submission::GROUP_TYPE_DONATION_RECEIPT,
));
if ($group_types['count'] > 0) {
$group_type = reset($group_types['values']);
$query = civicrm_api3('Group', 'get', array(
'is_active' => 1,
'group_type' => array('LIKE' => '%' . CRM_Utils_Array::implodePadded($group_type['value']) . '%'),
'option.limit' => 0,
'return' => 'id,name'
));
foreach ($query['values'] as $group) {
$groups[$group['id']] = $group['name'];
}
}
else {
$groups[''] = E::ts('No donation receipt groups available');
}
return $groups;
}
}

View file

@ -0,0 +1,190 @@
<?php
/*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*/
use CRM_Twingle_ExtensionUtil as E;
/**
* Form controller class
*
* @see https://wiki.civicrm.org/confluence/display/CRMDOC/QuickForm+Reference
*/
class CRM_Twingle_Form_Settings extends CRM_Core_Form {
private $_settingFilter = array('group' => 'de.systopia.twingle');
//everything from this line down is generic & can be re-used for a setting form in another extension
//actually - I lied - I added a specific call in getFormSettings
private $_submittedValues = array();
private $_settings = array();
/**
* @inheritdoc
*/
function buildQuickForm() {
// Set redirect destination.
$this->controller->_destination = CRM_Utils_System::url('civicrm/admin/settings/twingle', 'reset=1');
$settings = $this->getFormSettings();
$form_elements = array();
foreach ($settings as $name => $setting) {
if (isset($setting['quick_form_type'])) {
$add = 'add' . $setting['quick_form_type'];
if ($add == 'addElement') {
$this->$add(
$setting['html_type'],
$name,
ts($setting['title']),
CRM_Utils_Array::value('html_attributes', $setting, array())
);
}
elseif ($setting['html_type'] == 'Select') {
$optionValues = array();
if (!empty($setting['pseudoconstant']) && !empty($setting['pseudoconstant']['optionGroupName'])) {
$optionValues = CRM_Core_OptionGroup::values($setting['pseudoconstant']['optionGroupName'], FALSE, FALSE, FALSE, NULL, 'name');
}
$this->add(
'select',
$setting['name'],
$setting['title'],
$optionValues,
FALSE,
CRM_Utils_Array::value('html_attributes', $setting, array())
);
}
else {
$this->$add($name, ts($setting['title']));
}
$form_elements[$setting['name']] = array('description' => ts($setting['description']));
// Disable CiviSEPA setting if the extension is not installed.
if ($name == 'twingle_use_sepa') {
$sepa_extension = civicrm_api3('Extension', 'get', array(
'full_name' => 'org.project60.sepa',
'is_active' => 1,
));
if ($sepa_extension['count'] == 0) {
$element = $this->getElement('twingle_use_sepa');
$element->freeze();
$form_elements['twingle_use_sepa']['description'] .= ' <span class="error">The <a href="https://github.com/project60/org.project60.sepa" target="_blank" title="Extension page">CiviSEPA (<kbd>org.project60.sepa</kbd>) extension</a> is not installed.</span>';
}
}
}
}
$this->assign('formElements', $form_elements);
$this->addButtons(array(
array (
'type' => 'submit',
'name' => ts('Save'),
'isDefault' => TRUE,
)
));
// Export form elements.
$this->assign('elementNames', $this->getRenderableElementNames());
parent::buildQuickForm();
}
/**
* @inheritdoc
*/
function postProcess() {
$this->_submittedValues = $this->exportValues();
$this->saveSettings();
parent::postProcess();
}
/**
* Get the fields/elements defined in this form.
*
* @return array (string)
*/
function getRenderableElementNames() {
// The _elements list includes some items which should not be
// auto-rendered in the loop -- such as "qfKey" and "buttons". These
// items don't have labels. We'll identify renderable by filtering on
// the 'label'.
$elementNames = array();
foreach ($this->_elements as $element) {
/* @var \HTML_QuickForm_element $element */
$label = $element->getLabel();
if (!empty($label)) {
$elementNames[] = $element->getName();
}
}
return $elementNames;
}
/**
* Get the settings we are going to allow to be set on this form.
*
* @return array
*/
function getFormSettings() {
if (empty($this->_settings)) {
$settings = civicrm_api3('setting', 'getfields', array('filters' => $this->_settingFilter));
$settings = $settings['values'];
}
else {
$settings = $this->_settings;
}
return $settings;
}
/**
* Save the settings set on this form.
*/
function saveSettings() {
$settings = $this->getFormSettings();
$values = array_intersect_key($this->_submittedValues, $settings);
civicrm_api3('setting', 'create', $values);
}
/**
* @inheritdoc
*/
function setDefaultValues() {
$existing = civicrm_api3('setting', 'get', array('return' => array_keys($this->getFormSettings())));
$defaults = array();
$domainID = CRM_Core_Config::domainID();
foreach ($existing['values'][$domainID] as $name => $value) {
$defaults[$name] = $value;
}
return $defaults;
}
/**
* @inheritdoc
*/
public function addRules() {
$this->addFormRule(array('CRM_Twingle_Form_Settings', 'validateSettingsForm'));
}
/**
* Validates the profile form.
*
* @param array $values
* The submitted form values, keyed by form element name.
*
* @return bool | array
* TRUE when the form was successfully validated, or an array of error
* messages, keyed by form element name.
*/
public static function validateSettingsForm($values) {
$errors = array();
return empty($errors) ? TRUE : $errors;
}
}

View file

@ -0,0 +1,24 @@
<?php
/*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*/
use CRM_Twingle_ExtensionUtil as E;
class CRM_Twingle_Page_Configuration extends CRM_Core_Page {
public function run() {
parent::run();
}
}

View file

@ -0,0 +1,33 @@
<?php
/*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*/
use CRM_Twingle_ExtensionUtil as E;
class CRM_Twingle_Page_Profiles extends CRM_Core_Page {
public function run() {
$profiles = array();
foreach (CRM_Twingle_Profile::getProfiles() as $profile_name => $profile) {
$profiles[$profile_name]['name'] = $profile_name;
foreach (CRM_Twingle_Profile::allowedAttributes() as $attribute) {
$profiles[$profile_name][$attribute] = $profile->getAttribute($attribute);
}
}
$this->assign('profiles', $profiles);
parent::run();
}
}

View file

@ -56,7 +56,6 @@ class CRM_Twingle_Profile {
);
}
/**
* Checks whether the profile's selector matches the given project ID.
*
@ -166,16 +165,45 @@ class CRM_Twingle_Profile {
* @return array
*/
public static function allowedAttributes() {
// TODO: Adjust attributes for Twingle.
return array(
'selector',
'location_type_id',
'financial_type_id',
'campaign_id',
'pi_banktransfer',
'pi_debit_manual',
'pi_debit_automatic',
'pi_creditcard',
'pi_sepa',
'pi_mobilephone_germany',
'pi_paypal',
'groups',
'pi_sofortueberweisung',
'pi_amazonpay',
'pi_paydirekt',
'pi_applepay',
'pi_googlepay',
'newsletter_groups',
'postinfo_groups',
'donation_receipt_groups'
);
}
/**
* Retrieves a list of supported payment methods.
*
* @return array
*/
public static function paymentInstruments() {
return array(
'pi_banktransfer' => E::ts('Bank transfer'),
'pi_debit_manual' => E::ts('Debit manual'),
'pi_debit_automatic' => E::ts('Debit automatic'),
'pi_creditcard' => E::ts('Credit card'),
'pi_mobilephone_germany' => E::ts('Mobile phone Germany'),
'pi_paypal' => E::ts('PayPal'),
'pi_sofortueberweisung' => E::ts('SOFORT Überweisung'),
'pi_amazonpay' => E::ts('Amazon Pay'),
'pi_paydirekt' => E::ts('paydirekt'),
'pi_applepay' => E::ts('Apple Pay'),
'pi_googlepay' => E::ts('Google Pay'),
);
}
@ -188,16 +216,24 @@ class CRM_Twingle_Profile {
* @return CRM_Twingle_Profile
*/
public static function createDefaultProfile($name = 'default') {
// TODO: Adjust attributes for Twingle.
return new CRM_Twingle_Profile($name, array(
'selector' => '',
'location_type_id' => CRM_Twingle_Submission::LOCATION_TYPE_ID_WORK,
'financial_type_id' => 1, // "Donation"
'campaign_id' => '',
'pi_banktransfer' => 5, // "EFT"
'pi_debit_manual' => '', // TODO: SEPA
'pi_debit_automatic' => 3, // Debit
'pi_creditcard' => 1, // "Credit Card"
'pi_sepa' => 5, // "EFT"
'pi_paypal' => 3, // "Debit"
'groups' => '',
'pi_mobilephone_germany' => '',
'pi_paypal' => '',
'pi_sofortueberweisung' => '',
'pi_amazonpay' => '',
'pi_paydirekt' => '',
'pi_applepay' => '',
'pi_googlepay' => '',
'newsletter_groups' => '',
'postinfo_groups' => '',
'donation_receipt_groups' => '',
));
}
@ -212,18 +248,21 @@ class CRM_Twingle_Profile {
*/
public static function getProfileForProject($project_id) {
$profiles = self::getProfiles();
// If none matches, use the default profile.
$profile = $profiles['default'];
foreach ($profiles as $profile) {
if ($profile->matches($project_id)) {
return $profile;
break;
}
}
// No profile matched, return default profile.
return $profiles['default'];
return $profile;
}
/**
* Retrieves the profil with the given name.
* Retrieves the profile with the given name.
*
* @param $name
*

View file

@ -22,6 +22,21 @@ class CRM_Twingle_Submission {
*/
const LOCATION_TYPE_ID_WORK = 2;
/**
* The option value name of the group type for newsletter subscribers.
*/
const GROUP_TYPE_NEWSLETTER = 'Mailing List';
/**
* The option value name of the group type for postal mailing subscribers.
*/
const GROUP_TYPE_POSTINFO = ''; // TODO.
/**
* The option value name of the group type for donation receipt requesters.
*/
const GROUP_TYPE_DONATION_RECEIPT = ''; // TODO.
/**
* The default ID of the "Employer of" relationship type.
*/

View file

@ -339,6 +339,15 @@ function civicrm_api3_twingle_donation_Submit($params) {
);
}
// Save user_extrafield as contact note.
if (!empty($params['user_extrafield'])) {
civicrm_api3('Note', 'create', array(
'entity_table' => 'civicrm_contact',
'entity_id' => $contact_id,
'note' => $params['user_extrafield'],
));
}
// Organisation lookup.
if (!empty($params['organization_name'])) {
$organisation_data = array(
@ -378,6 +387,8 @@ function civicrm_api3_twingle_donation_Submit($params) {
}
}
// TODO: contact into newsletter, postinfo and donation_receipt groups.
// Create contribution or SEPA mandate.
$contribution_data = array(
'contact_id' => (isset($organisation_id) ? $organisation_id : $contact_id),
@ -396,7 +407,14 @@ function civicrm_api3_twingle_donation_Submit($params) {
'full_name' => 'org.project60.sepa',
'is_active' => 1,
));
if ($sepa_extension['count'] && CRM_Sepa_Logic_Settings::isSDD($contribution_data)) {
if (
CRM_Core_BAO_Setting::getItem(
'de.systopia.twingle',
'twingle_use_sepa'
)
&& $sepa_extension['count']
&& CRM_Sepa_Logic_Settings::isSDD($contribution_data)
) {
// If CiviSEPA is installed and the financial type is a CiviSEPA-one,
// create SEPA mandate (and recurring contribution, using "createfull" API
// action).

View file

@ -0,0 +1,34 @@
<?php
/*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*/
/*
* Settings metadata file
*/
return array(
'twingle_use_sepa' => array(
'group_name' => 'de.systopia.twingle',
'group' => 'de.systopia.twingle',
'name' => 'twingle_use_sepa',
'type' => 'Boolean',
'quick_form_type' => 'YesNo',
'html_type' => 'radio',
'title' => 'Use CiviSEPA',
'default' => 0,
'add' => '4.6',
'is_domain' => 1,
'is_contact' => 0,
'description' => 'Whether to provide CiviSEPA functionality for manual debit payment method. This requires the CiviSEPA (org.project60.sepa) extension be installed.',
),
);

View file

@ -0,0 +1,106 @@
{*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*}
<div class="crm-block crm-form-block">
{if $op == 'create' or $op == 'edit'}
<fieldset>
<legend>{ts domain="de.systopia.twingle"}General settings{/ts}</legend>
<table class="form-layout-compressed">
<tr class="crm-section">
<td class="label">{$form.name.label}</td>
<td class="content">{$form.name.html}</td>
</tr>
<tr class="crm-section">
<td class="label">{$form.selector.label}</td>
<td class="content">{$form.selector.html}</td>
</tr>
<tr class="crm-section">
<td class="label">{$form.location_type_id.label}</td>
<td class="content">{$form.location_type_id.html}</td>
</tr>
<tr class="crm-section">
<td class="label">{$form.financial_type_id.label}</td>
<td class="content">{$form.financial_type_id.html}</td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>{ts domain="de.systopia.twingle"}Payment methods{/ts}</legend>
<table class="form-layout-compressed">
{foreach key=pi_name item=pi_label from=$payment_instruments}
<tr class="crm-section {cycle values="odd,even"}">
<td class="label">{$form.$pi_name.label}</td>
<td class="content">{$form.$pi_name.html}</td>
</tr>
{/foreach}
</table>
</fieldset>
<fieldset>
<legend>{ts domain="de.systopia.twingle"}Groups{/ts}</legend>
<table class="form-layout-compressed">
<tr class="crm-section">
<td class="label">{$form.newsletter_groups.label}</td>
<td class="content">{$form.newsletter_groups.html}</td>
</tr>
<tr class="crm-section">
<td class="label">{$form.postinfo_groups.label}</td>
<td class="content">{$form.postinfo_groups.html}</td>
</tr>
<tr class="crm-section">
<td class="label">{$form.donation_receipts_groups.label}</td>
<td class="content">{$form.donation_receipts_groups.html}</td>
</tr>
</table>
</fieldset>
{elseif $op == 'delete'}
{if $profile_name}
{if $profile_name == 'default'}
<div class="status">{ts domain="de.systopia.twingle" 1=$profile_name}Are you sure you want to reset the default profile?{/ts}</div>
{else}
<div class="status">{ts domain="de.systopia.twingle" 1=$profile_name}Are you sure you want to delete the profile <em>%1</em>?{/ts}</div>
{/if}
{else}
<div class="crm-error">{ts domain="de.systopia.twingle"}Profile name not given or invalid.{/ts}</div>
{/if}
{/if}
{* FOOTER *}
<div class="crm-submit-buttons">
{include file="CRM/common/formButtons.tpl" location="bottom"}
</div>
</div>

View file

@ -0,0 +1,17 @@
{*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*}
{htxt id='id-twingle_use_sepa'}
{ts domain="de.systopia.twingle"}When the <a href="https://github.com/project60/org.project60.sepa" target="_blank" title="Extension page">CiviSEPA (<kbd>org.project60.sepa</kbd>) extension</a> is enabled and one of its payment instruments is assigned to a Twingle payment method (practically the <em>debit_manual</em> payment method), submitting a Twingle donation through the API will create a SEPA mandate with the given data.{/ts}
{/htxt}

View file

@ -0,0 +1,42 @@
{*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*}
<div class="crm-block crm-form-block crm-twingle-form-block">
{* HEADER *}
<div class="crm-submit-buttons">
{include file="CRM/common/formButtons.tpl" location="top"}
</div>
<table class="form-layout-compressed">
{foreach from=$elementNames item=elementName}
<tr class="crm-twingle-form-block-{$form.$elementName.name}">
<td class="label">{$form.$elementName.label} &nbsp;<a onclick='CRM.help("{$form.$elementName.label}", {literal}{"id":"id-{/literal}{$form.$elementName.name}{literal}","file":"CRM\/Twingle\/Form\/Settings"}{/literal}); return false;' href="#" title="{ts domain="de.systopia.twingle"}Help{/ts}" class="helpicon"></a></td>
<td>
{$form.$elementName.html}
<br />
<span class="description">
{$formElements.$elementName.description}
</span>
</td>
</tr>
{/foreach}
</table>
{* FOOTER *}
<div class="crm-submit-buttons">
{include file="CRM/common/formButtons.tpl" location="bottom"}
</div>
</div>

View file

@ -0,0 +1,25 @@
{*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*}
<div class="crm-block crm-content-block">
<div class="crm-submit-buttons">
<a href="{crmURL p="civicrm/admin/settings/twingle/profiles"}" title="{ts domain="de.systopia.twingle"}Profiles{/ts}" class="button">
<span>{ts domain="de.systopia.twingle"}Configure profiles{/ts}</span>
</a>
<a href="{crmURL p="civicrm/admin/settings/twingle/settings"}" title="{ts domain="de.systopia.twingle"}Settings{/ts}" class="button">
<span>{ts domain="de.systopia.twingle"}Configure extension settings{/ts}</span>
</a>
</div>
</div>

View file

@ -0,0 +1,55 @@
{*------------------------------------------------------------+
| SYSTOPIA Twingle Integration |
| Copyright (C) 2018 SYSTOPIA |
| Author: J. Schuppe (schuppe@systopia.de) |
+-------------------------------------------------------------+
| This program is released as free software under the |
| Affero GPL license. You can redistribute it and/or |
| modify it under the terms of this license which you |
| can read by viewing the included agpl.txt or online |
| at www.gnu.org/licenses/agpl.html. Removal of this |
| copyright header is strictly prohibited without |
| written permission from the original author(s). |
+-------------------------------------------------------------*}
<div class="crm-block crm-content-block crm-twingle-content-block">
<div class="crm-submit-buttons">
<a href="{crmURL p="civicrm/admin/settings/twingle/profile" q="op=create"}" title="{ts domain="de.systopia.twingle"}New profile{/ts}" class="button">
<span><i class="crm-i fa-plus-circle"></i> {ts domain="de.systopia.twingle"}New profile{/ts}</span>
</a>
</div>
{if !empty($profiles)}
<table>
<thead>
<tr>
<th>{ts domain="de.systopia.twingle"}Profile name{/ts}</th>
<th>{ts domain="de.systopia.twingle"}Properties{/ts}</th>
<th>{ts domain="de.systopia.twingle"}Operations{/ts}</th>
</tr>
</thead>
<tbody>
{foreach from=$profiles item=profile}
{assign var="profile_name" value=$profile.name}
<tr>
<td>{$profile.name}</td>
<td>
<div><strong>{ts domain="de.systopia.twingle"}Selector{/ts}:</strong> {$profile.selector}</div>
</td>
<td>
<a href="{crmURL p="civicrm/admin/settings/twingle/profile" q="op=edit&name=$profile_name"}" title="{ts domain="de.systopia.twingle" 1=$profile.name}Edit profile %1{/ts}" class="action-item crm-hover-button">{ts domain="de.systopia.twingle"}Edit{/ts}</a>
{if $profile_name == 'default'}
<a href="{crmURL p="civicrm/admin/settings/twingle/profile" q="op=delete&name=$profile_name"}" title="{ts domain="de.systopia.twingle" 1=$profile.name}Reset profile %1{/ts}" class="action-item crm-hover-button">{ts domain="de.systopia.twingle"}Reset{/ts}</a>
{else}
<a href="{crmURL p="civicrm/admin/settings/twingle/profile" q="op=delete&name=$profile_name"}" title="{ts domain="de.systopia.twingle" 1=$profile.name}Delete profile %1{/ts}" class="action-item crm-hover-button">{ts domain="de.systopia.twingle"}Delete{/ts}</a>
{/if}
</td>
</tr>
{/foreach}
</tbody>
</table>
{/if}
</div>

32
xml/Menu/twingle.xml Normal file
View file

@ -0,0 +1,32 @@
<?xml version="1.0"?>
<menu>
<item>
<path>civicrm/admin/settings/twingle</path>
<page_callback>CRM_Twingle_Page_Configuration</page_callback>
<title>Twingle API Configuration</title>
<access_arguments>administer CiviCRM</access_arguments>
<desc>Configure the Twingle API extension</desc>
<adminGroup>System Settings</adminGroup>
<icon>admin/option.png</icon>
</item>
<item>
<path>civicrm/admin/settings/twingle/settings</path>
<page_callback>CRM_Twingle_Form_Settings</page_callback>
<title>Twingle API Settings</title>
<access_arguments>administer CiviCRM</access_arguments>
</item>
<item>
<path>civicrm/admin/settings/twingle/profiles</path>
<page_callback>CRM_Twingle_Page_Profiles</page_callback>
<title>Twingle API profile settings</title>
<access_arguments>administer CiviCRM</access_arguments>
<desc>Configure profiles for the Twingle API extension</desc>
<icon>admin/option.png</icon>
</item>
<item>
<path>civicrm/admin/settings/twingle/profile</path>
<page_callback>CRM_Twingle_Form_Profile</page_callback>
<title>Twingle Profile</title>
<access_arguments>administer CiviCRM</access_arguments>
</item>
</menu>