Merge branch 'IHK-Projekt' into main

This commit is contained in:
Marc Michalsky forumZFD 2021-04-13 08:56:08 +02:00
commit a658190a68
Signed by untrusted user who does not match committer: marc.koch
GPG key ID: 12406554CFB028B9
34 changed files with 4516 additions and 978 deletions

View file

@ -10,6 +10,10 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
// OUT means: coming from the CiviCRM database
public const OUT = 'OUT';
public const PROJECT = 'TwingleProject';
public const EVENT = 'TwingleEvent';
protected $className;
protected $id;
@ -22,14 +26,13 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
protected $formattedValues;
/**
* ## Campaign constructor.
*
* @param array $values
* @param int|null $id
*/
protected function __construct(array $values, int $id = NULL) {
protected function __construct(array $values = [], int $id = NULL) {
$this->id = $id;
$tmpClassName = explode('_', get_class($this));
@ -51,7 +54,6 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
* @throws \Exception
*/
public function create(bool $no_hook = FALSE): bool {
// Prepare project values for import into database
$values_prepared_for_import = $this->values;
$this->formatValues(
@ -60,6 +62,7 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
);
$this->translateKeys(
$values_prepared_for_import,
$this->className,
self::IN
);
$this->formattedValues = $values_prepared_for_import;
@ -69,13 +72,25 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
);
// Set id
$values_prepared_for_import['id'] = $this->id;
if (isset($this->id)) {
$values_prepared_for_import['id'] = $this->id;
}
// Set a flag to not trigger the hook
if ($no_hook) {
$_SESSION['CiviCRM']['de.forumzfd.twinglecampaign']['no_hook'] = TRUE;
}
// Cast booleans to integers
foreach ($values_prepared_for_import as $key => $value) {
if ($value === false) {
$values_prepared_for_import[$key] = 0;
}
elseif ($value === true) {
$values_prepared_for_import[$key] = 1;
}
}
// Create campaign
$result = civicrm_api3('Campaign', 'create', $values_prepared_for_import);
@ -89,12 +104,11 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
return TRUE;
}
/**
* ## Update instance values
* This method updates the **$values** array of this instance with the values
* from the provided array if they are defined in
* *CRM/TwingleCampaign/resources/twingle_api_templates.json*
* *CRM/TwingleCampaign/resources/twingle_api_templates.php*
*
* @param array $values
* Array with values to update
@ -103,47 +117,33 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
// Update campaign values
$filter = Cache::getInstance()->getTemplates()[$this->className];
foreach ($values as $key => $value) {
if ($this->className == "TwingleProject" && $key == 'project_id') {
$this->values['id'] = $value;
}
elseif (in_array($key, $filter)) {
if ($this->in_array_r($key, $filter)) {
$this->values[$key] = $value;
}
elseif ($key == 'embed') {
self::setEmbedData($value);
}
elseif ($key == 'counter-url') {
self::setCounterUrl($value['url']);
}
}
}
/**
* ## Set embed data fields
* This method sets all embed data fields that are defined in
* *CRM/TwingleCampaign/resources/twingle_api_templates.json*
*
* @param array $embedData
* Array with embed data from Twingle API
* ## Complement campaign values
* Complement existing campaign values with new ones
* @param array $arrayToComplement
*/
public function setEmbedData(array $embedData) {
public function complement(array $arrayToComplement) {
$this->complement_r($this->values, $arrayToComplement);
$this->values = $arrayToComplement;
}
// Get all embed_data keys from template
$embed_data_keys = Cache::getInstance()
->getTemplates()['project_embed_data'];
// Transfer all embed_data values
foreach ($embed_data_keys as $key) {
if (array_key_exists($key, $embedData)) {
$this->values[$key] = $embedData[$key];
private function complement_r($orig, &$fill) {
foreach ($orig as $key => $value) {
if (is_array($value)) {
$this->complement_r($orig[$key], $fill[$key]);
} else {
$fill[$key] = $value;
}
}
}
public abstract function formatValues(array &$values, string $direction);
public static abstract function formatValues(array &$values, string $direction);
/**
* ## Translate array keys between CiviCRM Campaigns and Twingle
@ -156,17 +156,27 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
*
* @param array $values
* array of keys to translate
*
* @param string $campaignType
* const: Campaign::PROJECT or Campaign::EVENT
* @param string $direction
* const: Campaign::OUT or Campaign::OUT
*
* @throws Exception
* @throws \Exception
*/
public function translateKeys(array &$values, string $direction) {
public static function translateKeys(
array &$values,
string $campaignType,
string $direction) {
if ($campaignType != self::PROJECT && $campaignType != self::EVENT) {
throw new Exception(
"Invalid Parameter $campaignType for translateKeys()"
);
}
// Get translations for fields
$field_translations = Cache::getInstance()
->getTranslations()[$this->className];
->getTranslations()[$campaignType];
// Set the direction of the translation
if ($direction == self::OUT) {
@ -188,7 +198,6 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
}
}
/**
* ## Translate field names and custom field names
*
@ -256,18 +265,6 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
}
}
/**
* ## Set counter url
*
* @param String $counterUrl
* URL of the counter
*/
public function setCounterUrl(string $counterUrl) {
$this->values['counter'] = $counterUrl;
}
/**
* ## Delete Campaign
* Deletes this Campaign from CiviCRM
@ -287,7 +284,6 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
return ($result['is_error'] == 0);
}
/**
* ## Deactivate this campaign
*
@ -300,7 +296,6 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
return self::deactivateByid($this->id);
}
/**
* ## Deactivate campaign by ID
*
@ -335,10 +330,8 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
}
}
public abstract function getResponse(string $status): array;
/**
* ## Get timestamp
* Validates **$input** to be either a *DateTime string* or an *Unix
@ -370,10 +363,8 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
}
}
public abstract function lastUpdate();
/**
* ## Get DateTime
* Validates **$input** to be either a *DateTime string* or an *Unix
@ -407,7 +398,6 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
}
}
/**
* ## Get id
* Returns the **id** of this campaign.
@ -418,4 +408,52 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
return (int) $this->id;
}
/**
* Helper function to search a value in a multidimensional array.
*
* @param $needle
* @param $haystack
* @param bool $strict
*
* @return bool
*/
protected function in_array_r($needle, $haystack, $strict = false): bool {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) ||
(is_array($item) && $this->in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
/**
* Helper function to check if the provided field is of type Boolean
*
* @param $fieldName
* @param string $campaignType Campaign::PROJECT or Campaign::EVENT
*
* @return bool
* @throws \Exception
*/
public static function isBoolean($fieldName, string $campaignType): bool {
$fields = Cache::getInstance()->getCampaigns()['custom_fields'];
if ($campaignType == self::PROJECT) {
if (isset($fields['twingle_project_' . $fieldName])) {
return $fields['twingle_project_' . $fieldName]['data_type'] == 'Boolean';
}
else {
return FALSE;
}
}
elseif ($campaignType == self::EVENT) {
if (isset($fields['twingle_event_' . $fieldName])) {
return $fields['twingle_event_' . $fieldName]['data_type'] == 'Boolean';
}
else {
return FALSE;
}
}
throw new Exception('Unknown campaign type');
}
}

View file

@ -27,9 +27,12 @@ class CRM_TwingleCampaign_BAO_CampaignType {
}
/**
* @param bool $upgrade
* If true: Does not show UF message if campaign type already exists
*
* @throws \CiviCRM_API3_Exception
*/
public function create() {
public function create(bool $upgrade = false) {
$field = civicrm_api3(
'OptionValue',
@ -41,8 +44,7 @@ class CRM_TwingleCampaign_BAO_CampaignType {
]
);
if ($field['count'] == 0)
{
if ($field['count'] == 0) {
$this->results = civicrm_api3('OptionValue', 'create', $this->getSetAttributes());
$this->value = array_column($this->results['values'], 'value')[0];
@ -55,11 +57,10 @@ class CRM_TwingleCampaign_BAO_CampaignType {
}
else {
$error_message = $this->results['error_message'];
Civi::log()->error("Twingle Extension could not create new campaign type
for \"$this->label\": $error_message");
Civi::log()->error("Twingle Extension could not create new campaign type for \"$this->label\": $error_message");
}
}
else {
elseif (!$upgrade) {
$campaignType = self::fetch($this->name);
foreach ($this as $var => $value) {
if (array_key_exists($var, $campaignType->getSetAttributes())) {
@ -67,6 +68,9 @@ class CRM_TwingleCampaign_BAO_CampaignType {
}
}
}
else {
$this->value = $field['values'][0]['value'];
}
}
/**

View file

@ -53,11 +53,6 @@ class CRM_TwingleCampaign_BAO_CustomField {
if (array_key_exists($var, $attributes)) {
$this->$var = $attributes[$var];
}
// translate help_post
if ($this->help_post) {
$this->help_post = E::ts($this->help_post);
}
}
}
@ -65,9 +60,12 @@ class CRM_TwingleCampaign_BAO_CustomField {
/**
* Creates a CustomField by calling CiviCRM API v.3
*
* @param bool $upgrade
* If true: Does not show UF message if custom field already exists
*
* @throws \CiviCRM_API3_Exception
*/
public function create() {
public function create(bool $upgrade = false) {
// Check if the field already exists
$field = civicrm_api3(
@ -105,27 +103,21 @@ class CRM_TwingleCampaign_BAO_CustomField {
->error("$this->extensionName could not create new custom field
\"$this->name\" for group \"$this->custom_group_id\":
$this->result['error_message']");
CRM_Utils_System::setUFMessage("Creation of custom field '$this->name'
failed. Find more information in the logs.");
CRM_Utils_System::setUFMessage(E::ts('Creation of custom field \'%1\' failed. Find more information in the logs.', [1 => $this->name]));
}
// If there is not enough information: log simple error message
else {
Civi::log()
->error("$this->extensionName could not create new custom field:
$this->result['error_message']");
CRM_Utils_System::setUFMessage("Creation of custom field
failed. Find more information in the logs.");
CRM_Utils_System::setUFMessage(E::ts("Creation of custom field failed. Find more information in the logs."));
}
}
}
else {
CRM_Utils_System::setUFMessage("Creation of custom field '$this->name'
failed, because a custom field with that name already exists.
Find more information in the logs.");
elseif (!$upgrade) {
CRM_Utils_System::setUFMessage(E::ts('Creation of custom field \'%1\' failed, because a custom field with that name already exists. Find more information in the logs.', [1 => $this->name]));
Civi::log()
->error("$this->extensionName could not create new custom field
\"$this->name\" for group \"$this->custom_group_id\" because a
field with that name already exists.");
->error("$this->extensionName could not create new custom field \"$this->name\" for group \"$this->custom_group_id\" because a field with that name already exists.");
}
}
@ -165,16 +157,9 @@ class CRM_TwingleCampaign_BAO_CustomField {
if (!$name) {
$result = [];
// Get json file with all custom fields for this extension
$json_file = file_get_contents(E::path() .
'/CRM/TwingleCampaign/resources/campaigns.json');
$campaign_info = json_decode($json_file, TRUE);
// Log an error and throw an exception if the file cannot get read
if (!$campaign_info) {
Civi::log()->error("Could not read json file");
throw new Exception('Could not read json file');
}
// Get array with all custom fields for this extension
$campaign_info =
require E::path() . '/CRM/TwingleCampaign/resources/campaigns.php';
// Recursive method call with all custom field names from the json file
foreach ($campaign_info['custom_fields'] as $customField) {

View file

@ -41,9 +41,12 @@ class CRM_TwingleCampaign_BAO_CustomGroup {
}
/**
* @param bool $upgrade
* If true: Does not show UF message if custom group already exists
*
* @throws \CiviCRM_API3_Exception
*/
public function create() {
public function create(bool $upgrade = false) {
$field = civicrm_api3(
'CustomGroup',
@ -74,18 +77,21 @@ class CRM_TwingleCampaign_BAO_CustomGroup {
Civi::log()->error("$this->extensionName could not create new custom group
for \"$this->name\": $this->results['error_message']"
);
CRM_Utils_System::setUFMessage("Creation of custom group '$this->name'
failed. Find more information in the logs.");
CRM_Utils_System::setUFMessage(E::ts('Creation of custom group \'%1\' failed. Find more information in the logs.', [1 => $this->name]));
}
else {
Civi::log()->error("$this->extensionName could not create new
custom group: $this->results['error_message']");
CRM_Utils_System::setUFMessage("Creation of custom group
failed. Find more information in the logs.");
CRM_Utils_System::setUFMessage(E::ts('Creation of custom group failed. Find more information in the logs.'));
}
}
}
elseif (!$upgrade) {
CRM_Utils_System::setUFMessage(E::ts('Creation of custom group \'%1\' failed, because a custom group with that name already exists. Find more information in the logs.', [1 => $this->name]));
Civi::log()
->error("$this->extensionName could not create new custom group \"$this->name\" because a group with that name already exists.");
}
}
/**

View file

@ -33,11 +33,6 @@ class CRM_TwingleCampaign_BAO_OptionValue {
if (array_key_exists($var, $attributes)) {
$this->$var = $attributes[$var];
}
// translate description
if ($this->description) {
$this->description = E::ts($this->description);
}
}
}
@ -144,10 +139,9 @@ class CRM_TwingleCampaign_BAO_OptionValue {
if (!$name) {
$result = [];
// Get json file with all custom fields for this extension
$json_file = file_get_contents(E::path() .
'/CRM/TwingleCampaign/resources/option_values.json');
$option_values = json_decode($json_file, TRUE);
// Get all custom fields for this extension from option_values.php
$option_values =
include(E::path() . '/CRM/TwingleCampaign/resources/option_values.php');
// Log an error and throw an exception if the file cannot get read
if (!$option_values) {

View file

@ -1,6 +1,5 @@
<?php
use CRM_TwingleCampaign_BAO_TwingleProject as TwingleProject;
use CRM_TwingleCampaign_ExtensionUtil as E;
@ -79,11 +78,41 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
*/
public function getProject(int $projectId = NULL): ?array {
$url = empty($projectId)
? $this->protocol . 'project' . $this->baseUrl . 'by-organisation/' . $this->organisationId
: $this->protocol . 'project' . $this->baseUrl . $projectId;
// If no project id is provided, return all projects
if (empty($projectId)) {
$response = [];
$projects = $this->curlGet($this->protocol . 'project' .
$this->baseUrl . 'by-organisation/' . $this->organisationId);
foreach ($projects as $project) {
$response[] = $this->getProject($project['id']);
}
return $response;
}
// If a project id is provided, return only one project
else {
return $this->curlGet($url);
// Get all general project information
$project = $this->curlGet($this->protocol . 'project' .
$this->baseUrl . $projectId);
// Get project options
$project['project_options'] = $this->getProjectOptions($projectId);
// Get project payment methods
$project['payment_methods'] =
$this->getProjectPaymentMethods($projectId);
// Set last update time
$project['last_update'] = max(
$project['last_update'],
$project['project_options']['last_update'],
$project['payment_methods']['updated_at']
);
unset($project['project_options']['last_update']);
unset($project['payment_methods']['updated_at']);
return $project;
}
}
/**
@ -92,30 +121,79 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
*
* Returns an array with all project values.
*
* @param TwingleProject $project
* The TwingleProject object that should get pushed to Twingle
* @param array $project
* The project values array that should get pushed to Twingle
*
* @return array
* @throws \Exception
*/
public function pushProject(TwingleProject &$project): array {
public function pushProject(array $project): array {
// Get only those values from the TwingleProject object which Twingle expects
$values = $project->export();
// Prepare url for curl
if ($values['id']) {
$url = $this->protocol . 'project' . $this->baseUrl . $values['id'];
if (isset($project['project_options'])) {
$projectOptions = $project['project_options'];
unset($project['project_options']);
}
else {
$url = $this->protocol . 'project' . $this->baseUrl . 'by-organisation/' .
$this->organisationId;
if (isset($project['payment_methods'])) {
$paymentMethods = $project['payment_methods'];
unset($project['payment_methods']);
}
// Send curl and return result
return $this->curlPost($url, $values);
try {
if (!isset($project['id'])) {
$url = $this->protocol . 'project' . $this->baseUrl . 'by-organisation/' .
$this->organisationId;
// Post project values
$updatedProject = $this->curlPost($url, $project);
$url = $this->protocol . 'project' . $this->baseUrl .
$updatedProject['id'];
}
else {
$url = $this->protocol . 'project' . $this->baseUrl . $project['id'];
// Post project values
$updatedProject = $this->curlPost($url, $project);
}
// Post project_options
if (isset($projectOptions)) {
$updatedProject['project_options'] =
$this->curlPost($url . '/options', $projectOptions);
}
else {
$updatedProject['project_options'] = $this->getProjectOptions($updatedProject['id']);
}
// Post payment_methods
if (isset ($paymentMethods)) {
$this->curlPost($url . '/payment-methods', $paymentMethods);
}
$updatedProject['payment_methods'] =
$this->getProjectPaymentMethods($updatedProject['id']);
// Set last update time
$updatedProject['last_update'] = max(
$updatedProject['last_update'],
$updatedProject['project_options']['last_update'],
$updatedProject['payment_methods']['updated_at']
);
unset($updatedProject['project_options']['last_update']);
unset($updatedProject['payment_methods']['updated_at']);
return $updatedProject;
}
catch
(Exception $e) {
throw new Exception(
E::SHORT_NAME . 'Call to Twingle API failed: ' .
$e->getMessage()
);
}
}
/**
* ## Get event from Twingle
* Returns all events for the provided **$projectId** or a single event if an
@ -128,48 +206,48 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
* @throws Exception
*/
public function getEvent(int $projectId, int $eventId = NULL): array {
$result = [];
$result = [];
// Construct url for curl
$url = empty($eventId)
? $this->protocol . 'project' . $this->baseUrl . $projectId . '/event'
: $this->protocol . 'project' . $this->baseUrl . $projectId . '/event/'
. $eventId;
// Construct url for curl
$url = empty($eventId)
? $this->protocol . 'project' . $this->baseUrl . $projectId . '/event'
: $this->protocol . 'project' . $this->baseUrl . $projectId . '/event/'
. $eventId;
$offset = 0;
$finished = FALSE;
$offset = 0;
$finished = FALSE;
// Get only as much results per call as configured in $this->limit
while (!$finished) {
$params = [
'orderby' => 'id',
'direction' => 'desc',
'limit' => $this->limit,
'offset' => $offset,
'image' => 'as-boolean',
'public' => 0,
];
$response = $this->curlGet($url, $params);
// Get only as much results per call as configured in $this->limit
while (!$finished) {
$params = [
'orderby' => 'id',
'direction' => 'desc',
'limit' => $this->limit,
'offset' => $offset,
'image' => 'as-boolean',
'public' => 0,
];
$response = $this->curlGet($url, $params);
// If no $eventId was given, expect one or more events.
// Store the events, increase the offset and ask again until there
// are no more events incoming.
if (!$eventId) {
$result = array_merge($result, $response['data']);
$offset = $offset + $this->limit;
$finished = count($response['data']) < $this->limit;
}
// If $eventId was given, expect only one event
else {
// If the response array contains 'message', the $eventId does not exist
if (!$response['message']) {
$result = $response;
// If no $eventId was given, expect one or more events.
// Store the events, increase the offset and ask again until there
// are no more events incoming.
if (!$eventId) {
$result = array_merge($result, $response['data']);
$offset = $offset + $this->limit;
$finished = count($response['data']) < $this->limit;
}
// If $eventId was given, expect only one event
else {
// If the response array contains 'message', the $eventId does not exist
if (!$response['message']) {
$result = $response;
}
$finished = TRUE;
}
$finished = TRUE;
}
return $result;
}
return $result;
}
/**
* ## Get project embed data
@ -182,20 +260,49 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
*/
public function getProjectEmbedData($projectId): array {
$result = $this->getProject($projectId);
$result = $this->getProject($projectId);
if ($result['embed']) {
// Include counter url into embed data
$result['embed']['counter'] = $result['counter-url']['url'];
if ($result['embed']) {
// Include counter url into embed data
$result['embed']['counter'] = $result['counter-url']['url'];
return $result['embed'];
return $result['embed'];
}
else {
throw new Exception(
"Could not get embed data for project $projectId."
);
}
}
else {
throw new Exception(
"Could not get embed data for project $projectId."
);
/**
* ## Get project options
* Gets all project options from the Twingle API
*
* @param $projectId
*
* @return array
* @throws \Exception
*/
public function getProjectOptions($projectId): array {
$url = $this->protocol . 'project' . $this->baseUrl . $projectId . '/options';
return $this->curlGet($url);
}
/**
* ## Get project payment methods
* Gets all project payment methods from the Twingle API
*
* @param $projectId
*
* @return array
* @throws \Exception
*/
public function getProjectPaymentMethods($projectId): array {
$url = $this->protocol . 'project' . $this->baseUrl . $projectId
. '/payment-methods';
return $this->curlGet($url);
}
}
/**
@ -208,9 +315,9 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
* @throws Exception
*/
public function deleteProject(int $projectId): bool {
$url = $this->protocol . 'project' . $this->baseUrl . $projectId;
return $this->curlDelete($url);
}
$url = $this->protocol . 'project' . $this->baseUrl . $projectId;
return $this->curlDelete($url);
}
/**
@ -226,10 +333,10 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
* @throws Exception
*/
public function deleteEvent(int $projectId, int $eventId): bool {
$url = $this->protocol . 'project' . $this->baseUrl . $projectId .
'/event/' . $eventId;
return $this->curlDelete($url);
}
$url = $this->protocol . 'project' . $this->baseUrl . $projectId .
'/event/' . $eventId;
return $this->curlDelete($url);
}
/**
@ -267,7 +374,8 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
}
if ($curl_status_code == 404) {
throw new Exception('http status code 404 (not found)');
} elseif ($curl_status_code == 500) {
}
elseif ($curl_status_code == 500) {
throw new Exception('https status code 500 (internal error)');
}
return $response;
@ -309,9 +417,13 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
}
if ($curl_status_code == 404) {
throw new Exception('http status code 404 (not found)');
} elseif ($curl_status_code == 500) {
}
elseif ($curl_status_code == 500) {
throw new Exception('https status code 500 (internal error)');
}
if (sizeof($response) == 1 && isset($response['message'])) {
throw new Exception($response['message']);
}
return $response;
}
@ -352,7 +464,8 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
}
if ($curl_status_code == 404) {
throw new Exception('http status code 404 (not found)');
} elseif ($curl_status_code == 500) {
}
elseif ($curl_status_code == 500) {
throw new Exception('https status code 500 (internal error)');
}
return ($curl_status_code == 200);

View file

@ -26,7 +26,7 @@ class CRM_TwingleCampaign_BAO_TwingleCampaign {
*
* @throws \CiviCRM_API3_Exception
*/
public function __construct(array $values, int $id = NULL) {
public function __construct(array $values = [], int $id = NULL) {
$this->prefix = 'twingle_campaign_';
$this->id = $id ?? NULL;
@ -96,7 +96,7 @@ class CRM_TwingleCampaign_BAO_TwingleCampaign {
// Get campaign type id for TwingleProject
$twingle_project_campaign_type_id =
ExtensionCache::getInstance()
->getCampaigns()['campaign_types']['twingle_project']['id'];
->getCampaignIds()['campaign_types']['twingle_project']['id'];
// Determine the parent project id by looping through the campaign tree
// until the parent campaign type is a TwingleProject

View file

@ -19,7 +19,7 @@ class CRM_TwingleCampaign_BAO_TwingleEvent extends Campaign {
*
* @throws \Exception
*/
public function __construct(array $event, int $id = NULL) {
public function __construct(array $event = [], int $id = NULL) {
parent::__construct($event, $id);
$this->prefix = 'twingle_event_';
@ -100,7 +100,7 @@ class CRM_TwingleCampaign_BAO_TwingleEvent extends Campaign {
*
* @throws Exception
*/
public function formatValues(array &$values, string $direction) {
public static function formatValues(array &$values, string $direction) {
if ($direction == self::IN) {

View file

@ -2,10 +2,35 @@
use CRM_TwingleCampaign_Utils_ExtensionCache as Cache;
use CRM_TwingleCampaign_BAO_Campaign as Campaign;
use CRM_TwingleCampaign_Utils_StringOperations as StringOperations;
use CRM_TwingleCampaign_ExtensionUtil as E;
class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
// All available contact fields in Twingle project forms
const contactFields = [
'salutation',
'firstname',
'lastname',
'company',
'birthday',
'street',
'postal_code',
'city',
'country',
'telephone',
];
// All available donation rhythms in Twingle project forms
const donationRhythm = [
'yearly',
'halfyearly',
'quarterly',
'monthly',
'one_time',
];
/**
* ## TwingleProject constructor
*
@ -15,7 +40,16 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
* @param int|null $id
* CiviCRM Campaign id
*/
public function __construct(array $values, int $id = NULL) {
public function __construct(array $values = [], int $id = NULL) {
// If the $values originally come from the TwingleProject.get API, they
// contain the internal CiviCRM id as 'id' and the external Twingle id as
// 'project_id'. In this case 'id' gets replaced with 'project_id'
if (isset($values['project_id'])) {
$values['id'] = $values['project_id'];
unset($values['project_id']);
}
parent::__construct($values, $id);
$this->prefix = 'twingle_project_';
@ -25,36 +59,98 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
}
/**
* ## Export values
* Ensures that only those values will be exported which the Twingle API
* expects. These values are defined in
* *CRM/TwingleCampaign/resources/twingle_api_templates.json*
* Change all values to a format accepted by the Twingle API.
*
* @return array
* Array with all values to send to the Twingle API
*
* @throws Exception
* Array with all values ready to send to the Twingle API
* @throws \Exception
*/
public function export(): array {
// copy project values
$values = $this->values;
self::formatValues($values, self::OUT);
// Get template for project
$project = Cache::getInstance()->getTemplates()['TwingleProject'];
// Strings to booleans
$this->intToBool($values);
// Replace array items which the Twingle API does not expect
foreach ($values as $key => $value) {
if (!in_array($key, $project)) {
unset($values[$key]);
}
// Strings to integers
$this->strToInt($values);
// Build counter-url array
if (isset($values['counter-url']) && is_string($values['counter-url'])) {
$url = $values['counter-url'];
unset($values['counter-url']);
$values['counter-url']['url'] = $url;
}
// Remove campaign_type_id
unset($values['campaign_type_id']);
return $values;
}
/**
* ## Int to bool
* Changes all project values that are defined as CiviCRM 'Boolean' types
* from strings to booleans.
*
* @param array $values
*
* @throws \Exception
*/
private function intToBool(array &$values) {
$boolArrays = [
'payment_methods',
'donation_rhythm',
];
foreach ($values as $key => $value) {
if (CRM_TwingleCampaign_BAO_Campaign::isBoolean(
$key,
CRM_TwingleCampaign_BAO_Campaign::PROJECT
)) {
$values[$key] = (bool) $value;
}
elseif (in_array($key, $boolArrays)) {
foreach ($values[$key] as $_key => $_value) {
if (is_bool($_value)) {
// nothing to do here
}
elseif (is_numeric($_value) && $_value < 2 || empty($_value)) {
$values[$key][$_key] = (bool) $_value;
}
else {
unset($values[$key][$_key]);
}
}
}
elseif (is_array($value)) {
$this->intToBool($values[$key]);
}
}
}
/**
* ## Int to bool
* Changes all project values that are strings but originally came as integers
* back to integers.
*
* @param array $values
*
* @throws \Exception
*/
private function strToInt(array &$values) {
foreach ($values as $key => $value) {
if (ctype_digit($value)) {
$values[$key] = intval($value);
}
elseif (is_array($value)) {
$this->strToInt($values[$key]);
}
}
}
/**
* ## Create this TwingleProject as a campaign in CiviCRM
@ -80,10 +176,87 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
}
}
/**
* ## Update instance values
*
* @param array $values
*
* @override CRM_TwingleCampaign_BAO_Campaign::update()
*/
public function update(array $values) {
// Remove old values
unset($this->values);
// Get allowed values
$projectOptionsKeys = Cache::getInstance()
->getTemplates()['TwingleProject']['project_options'];
$projectEmbedDataKeys = Cache::getInstance()
->getTemplates()['TwingleProject']['project_embed_data'];
$projectPaymentMethodsKeys = Cache::getInstance()
->getTemplates()['TwingleProject']['payment_methods'];
// Sort allowed values into arrays
foreach ($values as $key => $value) {
if ($key == 'project_options') {
foreach ($value as $optionKey => $optionValue) {
if (in_array($optionKey, $projectOptionsKeys)) {
$this->values['project_options'][$optionKey] = $optionValue;
}
}
}
elseif ($key == 'embed') {
foreach ($value as $embedKey => $embedValue) {
if (in_array($embedKey, $projectEmbedDataKeys)) {
$this->values['embed'][$embedKey] = $embedValue;
}
}
}
elseif ($key == 'payment_methods') {
foreach ($value as $paymentMethodKey => $paymentMethodValue) {
if (in_array($paymentMethodKey, $projectPaymentMethodsKeys)) {
$this->values['payment_methods'][$paymentMethodKey] =
$paymentMethodValue;
}
}
}
elseif ($key == 'counter-url' && is_array($value)) {
$this->values['counter-url'] = $value['url'];
}
else {
parent::update([$key => $value]);
}
}
}
/**
* ## Complement campaign values
* Complement existing campaign values with new ones
*
* @param array $arrayToComplement
*
* @overrides CRM_TwingleCampaign_BAO_Campaign
*/
public function complement(array $arrayToComplement) {
// Set all contact fields to false
if (
isset($arrayToComplement['values']['project_options']['contact_fields'])
) {
foreach (
$arrayToComplement['values']['project_options']['contact_fields']
as $key => $value
) {
$arrayToComplement['values']['project_options']['contact_fields'][$key]
= FALSE;
}
}
parent::complement($arrayToComplement);
}
/**
* ## Clone this TwingleProject
*
* This method removes the id and the identifier from this instance and in
* the next step it pushes the clone as a new project with the same values to
* Twingle.
@ -91,11 +264,163 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
* @throws \Exception
*/
public function clone() {
$this->values['id'] = 0;
$this->values['identifier'] = 0;
$this->values['id'] = '';
$this->values['identifier'] = '';
$this->create(); // this will also trigger the postSave hook
}
/**
* ## Validate
* Validates project values and returns an array containing the result and
* another array with eventual error messages.
*
* @return array ['valid' => bool, 'messages' => array]
*/
public function validate(): array {
$valid = TRUE;
$messages = [];
// Validate email address
if (
!filter_var(
$this->values['project_options']['bcc_email_address'],
FILTER_VALIDATE_EMAIL
)
&& !empty($this->values['project_options']['bcc_email_address'])
) {
$valid = FALSE;
$messages[] = E::ts("BCC email invalid");
}
// Validate hexadecimal color fields
$colorFields =
[
'design_background_color',
'design_primary_color',
'design_font_color',
];
foreach ($colorFields as $colorField) {
if (
!empty($this->values['project_options'][$colorField]) &&
(
!(
ctype_xdigit($this->values['project_options'][$colorField]) ||
is_integer($this->values['project_options'][$colorField])
) ||
strlen((string) $this->values['project_options'][$colorField]) > 6
)
) {
$valid = FALSE;
$messages[] =
E::ts("Invalid hexadecimal value in color field: %1",
[1 => $colorField]);
}
}
// Check if donation values are integers and if proposed donation value
// lies between max and min values
if (
// Is integer and >= 0 or empty
(
empty($this->values['project_options']['donation_value_default']) ||
(
is_integer($this->values['project_options']['donation_value_default']) ||
ctype_digit($this->values['project_options']['donation_value_default'])
) && (
$this->values['project_options']['donation_value_default'] >= 0
)
) && (
empty($this->values['project_options']['donation_value_min']) ||
(
is_integer($this->values['project_options']['donation_value_min']) ||
ctype_digit($this->values['project_options']['donation_value_min'])
) && (
$this->values['project_options']['donation_value_max'] >= 0
)
) && (
empty($this->values['project_options']['donation_value_max']) ||
(
is_integer($this->values['project_options']['donation_value_max']) ||
ctype_digit($this->values['project_options']['donation_value_max'])
) && (
$this->values['project_options']['donation_value_max'] >= 0
)
)
) {
if (
// all empty
empty($this->values['project_options']['donation_value_default']) &&
empty($this->values['project_options']['donation_value_min']) &&
empty($this->values['project_options']['donation_value_max'])
) {
// nothing to validate
}
elseif (
// Max empty, min not empty
(!empty($this->values['project_options']['donation_value_min']) &&
empty($this->values['project_options']['donation_value_max'])) ||
// Max empty, default not empty
(!empty($this->values['project_options']['donation_value_default']) &&
empty($this->values['project_options']['donation_value_max']))
) {
$valid = FALSE;
$messages[] =
E::ts("Missing maximum donation value");
}
else {
if (
// Min >= Max
$this->values['project_options']['donation_value_min'] >=
$this->values['project_options']['donation_value_max']
) {
$valid = FALSE;
$messages[] =
E::ts("Maximum donation value must be higher than the minimum");
}
elseif (
// Default < min or default > max
$this->values['project_options']['donation_value_default'] <
$this->values['project_options']['donation_value_min'] ||
$this->values['project_options']['donation_value_default'] >
$this->values['project_options']['donation_value_max']
) {
$valid = FALSE;
$messages[] =
E::ts("Default donation value must lie in between maximum and minimum values");
}
}
}
else {
$valid = FALSE;
$messages[] =
E::ts("Donation values (Min, Max, Default) must be positive integers");
}
// Validate sharing url
$urlFields =
[
'custom_css',
'share_url',
];
foreach ($urlFields as $urlField) {
if (!empty($this->values['project_options'][$urlField])) {
if (
!filter_var(
$this->values['project_options'][$urlField],
FILTER_VALIDATE_URL
) || empty($this->values['project_options'][$urlField])
) {
$valid = FALSE;
$messages[] =
E::ts("Invalid URL: %1", [1 => $urlField]);
}
}
}
return ['valid' => $valid, 'messages' => $messages];
}
/**
* ## Translate values between CiviCRM Campaigns and Twingle formats
@ -114,23 +439,128 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
*
* @throws Exception
*/
public function formatValues(array &$values, string $direction) {
public
static function formatValues(array &$values, string $direction) {
if ($direction == self::IN) {
// Change timestamp into DateTime string
if ($values['last_update']) {
if (isset($values['last_update'])) {
$values['last_update'] =
self::getDateTime($values['last_update']);
}
// empty project_type to 'default'
if (!$values['type']) {
if (empty($values['type'])) {
$values['type'] = 'default';
}
// Flatten project options array
foreach ($values['project_options'] as $key => $value) {
$values[$key] = $value;
}
unset($values['project_options']);
// Flatten embed codes array
foreach ($values['embed'] as $key => $value) {
$values[$key] = $value;
}
unset($values['embed']);
// Flatten button array
if (isset($values['buttons'])) {
foreach (
$values['buttons'] as $button_key => $button
) {
$values[$button_key] = $button['amount'];
}
unset($values['buttons']);
}
// Invert and explode exclude_contact_fields
if (isset($values['exclude_contact_fields'])) {
$values['contact_fields'] =
array_diff(
self::contactFields,
explode(',', $values['exclude_contact_fields'])
);
unset($values['exclude_contact_fields']);
}
// Explode mandatory_contact_fields
if (isset($values['mandatory_contact_fields'])) {
$values['mandatory_contact_fields'] =
explode(
',',
$values['mandatory_contact_fields']
);
unset($values['mandatory_contact_fields']);
}
// Explode languages
if (isset($values['languages'])) {
$values['languages'] =
explode(',', $values['languages']);
}
// Divide payment methods array into one time and recurring payment
// methods arrays containing only TRUE payment methods
foreach ($values['payment_methods'] as $key => $value) {
if ($value) {
if (StringOperations::endsWith($key, 'recurring')) {
$values['payment_methods_recurring'][] = $key;
}
else {
$values['payment_methods'][] = $key;
}
}
unset($values['payment_methods'][$key]);
}
// Transform donation rhythm array to contain only TRUE elements
foreach ($values['donation_rhythm'] as $key => $value) {
if ($value) {
$values['donation_rhythm'][] = $key;
}
unset($values['donation_rhythm'][$key]);
}
}
elseif ($direction == self::OUT) {
$projectOptionsKeys = Cache::getInstance()
->getTemplates()['TwingleProject']['project_options'];
$projectEmbedDataKeys = Cache::getInstance()
->getTemplates()['TwingleProject']['project_embed_data'];
// Merge payment_methods and payment_methods_recurring arrays and change
// keys to values and values to TRUE
if (isset($values['payment_methods'])) {
foreach ($values['payment_methods'] as $key => $value) {
unset($values['payment_methods'][$key]);
$values['payment_methods'][$value] = TRUE;
}
}
if (isset($values['payment_methods_recurring'])) {
foreach ($values['payment_methods_recurring'] as $value) {
$values['payment_methods'][$value] = TRUE;
}
unset($values['payment_methods_recurring']);
}
// Move options, embed data and payment methods into own arrays
foreach ($values as $key => $value) {
if (in_array($key, $projectOptionsKeys)) {
$values['project_options'][$key]
= $value;
unset($values[$key]);
}
elseif (in_array($key, $projectEmbedDataKeys)) {
$values['embed_data'][$key]
= $value;
unset($values[$key]);
}
}
// Change DateTime string into timestamp
$values['last_update'] =
self::getTimestamp($values['last_update']);
@ -141,19 +571,80 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
: $values['type'];
// Cast project target to integer
$values['project_target'] = (int) $values['project_target'];
if (isset($values['project_target'])) {
$values['project_target'] = (int) $values['project_target'];
}
// Set default for 'allow_more'
$values['allow_more'] = empty($values['allow_more'])
? FALSE
: TRUE;
$values['allow_more'] = !empty($values['allow_more']);
// Invert and concatenate contact fields
if (isset($values['project_options']['contact_fields'])) {
// Invert contact_fields to exclude_contact_fields
$values['project_options']['exclude_contact_fields'] =
array_diff(
self::contactFields,
$values['project_options']['contact_fields']
);
unset($values['project_options']['contact_fields']);
// Concatenate contact_fields array
$values['project_options']['exclude_contact_fields'] =
implode(
',',
$values['project_options']['exclude_contact_fields']
);
}
// Concatenate mandatory project contact fields
if (isset($values['project_options']['mandatory_contact_fields'])) {
$values['project_options']['mandatory_contact_fields'] =
implode(
',',
$values['project_options']['mandatory_contact_fields']
);
}
// Concatenate project languages
if (isset($values['project_options']['languages'])) {
$values['project_options']['languages'] =
implode(',', $values['project_options']['languages']);
}
// Build donation_rhythm array
if (isset($values['project_options']['donation_rhythm'])) {
$tmp_array = [];
foreach (self::donationRhythm as $donationRhythm) {
$tmp_array[$donationRhythm] =
in_array(
$donationRhythm,
$values['project_options']['donation_rhythm']
);
}
$values['project_options']['donation_rhythm'] = $tmp_array;
}
// Build payment_methods_array
if (isset($values['payment_methods'])) {
$payment_methods = array_fill_keys(Cache::getInstance()
->getTemplates()['TwingleProject']['payment_methods'],
FALSE);
$values['payment_methods'] =
array_merge($payment_methods, $values['payment_methods']);
}
// Build buttons array
for ($i = 1; $i <= 4; $i++) {
if (isset($values['button' . $i])) {
$values['project_options']['buttons']['button' . $i] =
['amount' => $values['button' . $i]];
unset($values['button' . $i]);
}
}
}
else {
throw new Exception(
"Invalid Parameter $direction for formatValues()"
);
}
}
@ -170,7 +661,8 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
* @return array
*
*/
public function getResponse(string $status = NULL): array {
public
function getResponse(string $status = NULL): array {
$project_type = empty($this->values['type']) ? 'default' : $this->values['type'];
$response =
[
@ -185,26 +677,88 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
return $response;
}
/**
* ## Last update
* Returns a timestamp of the last update of the TwingleProject campaign.
*
* @return int|string|null
* @return int|null
*/
public function lastUpdate() {
public function lastUpdate(): ?int {
return self::getTimestamp($this->values['last_update']);
}
/**
* ## Get project id
* Returns the **project_id** of this TwingleProject.
*
* @return int
*/
public function getProjectId(): int {
public
function getProjectId(): int {
return (int) $this->values['id'];
}
/**
* ## Get the payment methods array of this project
*
* @return array
*/
public function getValues(): array {
if (isset($this->values)) {
return $this->values;
}
else {
return [];
}
}
/**
* ## Get the project options array of this project
*
* @return array
*/
public function getOptions(): array {
if (isset($this->values['project_options'])) {
return $this->values['project_options'];
}
else {
return [];
}
}
/**
* ## Get the payment methods array of this project
*
* @return array
*/
public function getPaymentMethods(): array {
if (isset($this->values['payment_methods'])) {
return $this->values['payment_methods'];
}
else {
return [];
}
}
/**
* ## Get the payment methods array of this project
*/
public function deleteValues(): void {
unset ($this->values);
}
/**
* ## Get the project options array of this project
*/
public function deleteOptions(): void {
unset($this->values['project_options']);
}
/**
* ## Get the payment methods array of this project
*/
public function deletePaymentMethods(): void {
unset($this->values['payment_methods']);
}
}

View file

@ -16,15 +16,61 @@ class CRM_TwingleCampaign_Upgrader extends CRM_TwingleCampaign_Upgrader_Base {
// By convention, functions that look like "function upgrade_NNNN()" are
// upgrade tasks. They are executed in order (like Drupal's hook_update_N).
/**
* @throws \CiviCRM_API3_Exception
*/
public function upgrade_01() {
$campaign_info = require E::path() .
'/CRM/TwingleCampaign/resources/campaigns.php';
$option_values = require E::path() .
'/CRM/TwingleCampaign/resources/option_values.php';
// Create campaign types
foreach ($campaign_info['campaign_types'] as $campaign_type) {
new CampaignType($campaign_type);
}
foreach (CampaignType::getCampaignTypes() as $campaign_type) {
$campaign_type->create(true);
}
// Create custom groups
foreach ($campaign_info['custom_groups'] as $custom_group) {
foreach (CampaignType::getCampaignTypes() as $campaign_type) {
if ($campaign_type->getName() == $custom_group['campaign_type']) {
$custom_group['extends_entity_column_value'] = $campaign_type->getValue();
}
}
$cg = new CustomGroup($custom_group);
$cg->create(true);
}
// Create custom fields
foreach ($campaign_info['custom_fields'] as $custom_field) {
$cf = new CustomField($custom_field);
$cf->create(true);
}
// Create option values
foreach ($option_values as $option_value) {
$ov = new OptionValue($option_value);
$ov->create();
}
return TRUE;
}
/**
* @throws \Exception
*/
public function install() {
// Create campaign types, custom fields and custom groups by the contents
// of the json file "campaigns.json"
// of the campaigns.php file
$campaign_info = Cache::getInstance()->getCampaigns();
$option_values = Cache::getInstance()->getOptionValues();
$campaign_info = require E::path() .
'/CRM/TwingleCampaign/resources/campaigns.php';
$option_values = require E::path() .
'/CRM/TwingleCampaign/resources/option_values.php';
// Create campaign types
foreach ($campaign_info['campaign_types'] as $campaign_type) {
@ -88,7 +134,8 @@ class CRM_TwingleCampaign_Upgrader extends CRM_TwingleCampaign_Upgrader_Base {
*/
public function uninstall() {
$campaign_info = Cache::getInstance()->getCampaigns();
$campaign_info = require E::path() .
'/CRM/TwingleCampaign/resources/campaigns.php';
$option_values = Cache::getInstance()->getOptionValues();
// Delete campaign types

View file

@ -13,13 +13,7 @@ class CRM_TwingleCampaign_Utils_ExtensionCache {
private $customFieldMapping;
private $translations;
private $campaigns;
private $templates;
private $option_values;
private $campaignIds;
/**
* ## Get an instance (singleton)
@ -44,37 +38,11 @@ class CRM_TwingleCampaign_Utils_ExtensionCache {
// Get a mapping of custom fields
$this->customFieldMapping = CustomField::getMapping();
// Initialize json files as arrays
$file_paths = [
'translations' => '/CRM/TwingleCampaign/resources/dictionary.json',
'templates' => '/CRM/TwingleCampaign/resources/twingle_api_templates.json',
'campaigns' => '/CRM/TwingleCampaign/resources/campaigns.json',
'option_values' => '/CRM/TwingleCampaign/resources/option_values.json',
];
foreach ($file_paths as $key => $file_path) {
// Get array from json file
$file_path = E::path() . $file_path;
$json_file = file_get_contents($file_path);
$json_file_name = pathinfo($file_path)['filename'];
$array = json_decode($json_file, TRUE);
// Throw and log an error if json file can't be read
if (!$array) {
$message = ($json_file_name)
? "Could not read json file $json_file_name"
: "Could not locate json file in path: $file_path";
Civi::log()->error($message);
throw new Exception($message);
}
// Set attribute
$this->$key = $array;
}
// Get ids for Twingle related campaign types
foreach ($this->campaigns['campaign_types'] as $campaign_type) {
$this->campaignIds = require(
E::path() . '/CRM/TwingleCampaign/resources/campaigns.php'
);
foreach ($this->campaignIds['campaign_types'] as $campaign_type) {
$campaign_type_id = civicrm_api3(
'OptionValue',
'get',
@ -85,7 +53,7 @@ class CRM_TwingleCampaign_Utils_ExtensionCache {
]
)['values'];
if ($campaign_type_id) {
$this->campaigns['campaign_types'][$campaign_type['name']]['id'] =
$this->campaignIds['campaign_types'][$campaign_type['name']]['id'] =
$campaign_type_id[0]['value'];
}
}
@ -114,28 +82,43 @@ class CRM_TwingleCampaign_Utils_ExtensionCache {
* @return array
*/
public function getTranslations(): array {
return $this->translations;
return require(
E::path() . '/CRM/TwingleCampaign/resources/dictionary.php'
);
}
/**
* @return array
*/
public function getCampaigns(): array {
return $this->campaigns;
return require(
E::path() . '/CRM/TwingleCampaign/resources/campaigns.php'
);
}
/**
* @return array
*/
public function getCampaignIds(): array {
return $this->campaignIds;
}
/**
* @return array
*/
public function getTemplates(): array {
return $this->templates;
return require(
E::path() . '/CRM/TwingleCampaign/resources/twingle_api_templates.php'
);
}
/**
* @return mixed
*/
public function getOptionValues() {
return $this->option_values;
return require(
E::path() . '/CRM/TwingleCampaign/resources/option_values.php'
);
}
}

View file

@ -51,4 +51,24 @@ class CRM_TwingleCampaign_Utils_StringOperations {
}
return $string;
}
/**
* Checks if a string ands with another string.
* @param $haystack
* @param $needle
* @return bool
*/
public static function endsWith($haystack, $needle): bool {
return substr_compare($haystack, $needle, -strlen($needle)) === 0;
}
/**
* Checks if a string starts with another string.
* @param $haystack
* @param $needle
* @return bool
*/
public static function startsWith($haystack, $needle): bool {
return substr_compare($haystack, $needle, 0, strlen($needle)) === 0;
}
}

View file

@ -1,469 +0,0 @@
{
"campaign_types": {
"twingle_project": {
"name": "twingle_project",
"label": "Twingle Project"
},
"twingle_event": {
"name": "twingle_event",
"label": "Twingle Event"
},
"twingle_campaign": {
"name": "twingle_campaign",
"label": "Twingle Campaign"
}
},
"custom_groups": {
"twingle_project_information": {
"title": "Twingle Project Information",
"name": "Twingle_Project_Information",
"extends": "Campaign",
"campaign_type": "twingle_project",
"weight": "1"
},
"twingle_project_embed_codes": {
"title": "Twingle Project Embed Codes",
"name": "Twingle_Project_Embed_Codes",
"extends": "Campaign",
"campaign_type": "twingle_project",
"collapse_display": "1",
"weight": "2"
},
"twingle_event_information": {
"title": "Twingle Event Information",
"name": "Twingle_Event_Information",
"extends": "Campaign",
"campaign_type": "twingle_event"
},
"twingle_campaign_information": {
"title": "Twingle Campaign Information",
"name": "Twingle_Campaign_Information",
"extends": "Campaign",
"campaign_type": "twingle_campaign"
}
},
"custom_fields": {
"twingle_project_id": {
"custom_group_id": "Twingle_Project_Information",
"label": "Twingle Project ID",
"name": "twingle_project_id",
"is_required": 0,
"is_searchable": 1,
"data_type": "String",
"html_type": "Text",
"text_length": 16,
"is_active": 1,
"is_view": 1,
"weight": 1
},
"twingle_project_organisation_id": {
"custom_group_id": "Twingle_Project_Information",
"label": "Twingle Project organisation ID",
"name": "twingle_project_organisation_id",
"is_required": 0,
"is_searchable": 1,
"data_type": "String",
"html_type": "Text",
"text_length": 32,
"is_active": 1,
"is_view": 1,
"weight": 6
},
"twingle_project_identifier": {
"custom_group_id": "Twingle_Project_Information",
"label": "Twingle Project identifier",
"name": "twingle_project_identifier",
"is_required": 0,
"is_searchable": 1,
"data_type": "String",
"html_type": "Text",
"text_length": 15,
"is_active": 1,
"is_view": 1,
"weight": 3,
"help_post": "An unique identifier for a project (auto generated)"
},
"twingle_project_type": {
"custom_group_id": "Twingle_Project_Information",
"label": "Twingle Project Type",
"name": "twingle_project_type",
"is_required": 0,
"is_searchable": 1,
"data_type": "String",
"html_type": "Select",
"option_values": {
"default": "Default",
"event": "Events",
"membership": "Membership"
},
"text_length": 32,
"is_active": 1,
"is_view": 0,
"weight": 2,
"help_post": "Choose the project type. Allow users to create own events or to pay a membership fee.",
"default_value": "default"
},
"twingle_project_allow_more": {
"custom_group_id": "Twingle_Project_Information",
"label": "Twingle Project allow more",
"name": "twingle_project_allow_more",
"is_required": 0,
"is_searchable": 1,
"data_type": "Boolean",
"html_type": "Radio",
"text_length": 4,
"is_active": 1,
"is_view": 0,
"weight": 4,
"help_post": "Allow to donate more than is defined in the target"
},
"twingle_project_transaction_type": {
"custom_group_id": "Twingle_Project_Information",
"label": "Twingle Project transaction type",
"name": "twingle_project_transaction_type",
"is_required": 0,
"is_searchable": 1,
"data_type": "String",
"html_type": "Text",
"text_length": 32,
"is_active": 1,
"is_view": 0,
"weight": 5
},
"twingle_project_url": {
"custom_group_id": "Twingle_Project_Information",
"label": "Twingle Project URL",
"name": "twingle_project_url",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 600,
"is_active": 1,
"is_view": 0,
"weight": 6
},
"twingle_project_widget": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Widget",
"name": "twingle_project_widget",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 600,
"is_active": 1,
"is_view": 1,
"weight": 1
},
"twingle_project_form": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Form",
"name": "twingle_project_form",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 600,
"is_active": 1,
"is_view": 1,
"weight": 2
},
"twingle_project_widget-single": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Widget Single",
"name": "twingle_project_widget-single",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 600,
"is_active": 1,
"is_view": 1,
"weight": 3
},
"twingle_project_form-single": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Form Single",
"name": "twingle_project_form-single",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 600,
"is_active": 1,
"is_view": 1,
"weight": 4
},
"twingle_project_eventall": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project All Events",
"name": "twingle_project_eventall",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 1300,
"is_active": 1,
"is_view": 1,
"weight": 5
},
"twingle_project_eventlist": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Event List",
"name": "twingle_project_eventlist",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 1300,
"is_active": 1,
"is_view": 1,
"weight": 6
},
"twingle_project_counter": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Counter",
"name": "twingle_project_counter",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 120,
"is_active": 1,
"is_view": 1,
"weight": 7
},
"twingle_project_page": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Page",
"name": "twingle_project_page",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 600,
"is_active": 1,
"is_view": 1,
"weight": 8
},
"twingle_event_id": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event ID",
"name": "twingle_event_id",
"is_required": 1,
"is_searchable": 1,
"data_type": "String",
"html_type": "Text",
"text_length": 16,
"is_active": 1,
"is_view": 1,
"weight": 1
},
"twingle_event_project_id": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Project ID",
"name": "twingle_event_project_id",
"is_required": 0,
"is_searchable": 1,
"data_type": "String",
"html_type": "Text",
"text_length": 16,
"is_active": 1,
"is_view": 1,
"weight": 2
},
"twingle_event_identifier": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Identifier",
"name": "twingle_event_identifier",
"is_required": 0,
"is_searchable": 0,
"data_type": "String",
"html_type": "Text",
"text_length": 16,
"is_active": 1,
"is_view": 1,
"weight": 3
},
"twingle_event_contact": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Initiator",
"name": "twingle_event_contact",
"is_required": 0,
"is_searchable": 1,
"data_type": "ContactReference",
"html_type": "Autocomplete-Select",
"is_active": 1,
"is_view": 0,
"weight": 5
},
"twingle_event_user_email": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Initiator Email",
"name": "twingle_event_user_email",
"is_required": 0,
"is_searchable": 0,
"data_type": "String",
"html_type": "Text",
"text_length": 128,
"is_active": 1,
"is_view": 1,
"weight": 6
},
"twingle_event_is_public": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event is public",
"name": "twingle_event_is_public",
"is_required": 0,
"is_searchable": 1,
"data_type": "Boolean",
"html_type": "Radio",
"is_active": 1,
"is_view": 1,
"weight": 7
},
"twingle_event_deleted": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Deleted",
"name": "twingle_event_deleted",
"is_required": 0,
"is_searchable": 1,
"data_type": "Boolean",
"html_type": "Radio",
"is_active": 1,
"is_view": 1,
"weight": 8
},
"twingle_event_confirmed_at": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Confirmed At",
"name": "twingle_event_confirmed_at",
"is_required": 0,
"is_searchable": 0,
"data_type": "String",
"html_type": "Text",
"text_length": 64,
"is_active": 1,
"is_view": 1,
"weight": 9
},
"twingle_event_created_at": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Created At",
"name": "twingle_event_created_at",
"is_required": 0,
"is_searchable": 0,
"data_type": "String",
"html_type": "Text",
"text_length": 64,
"is_active": 1,
"is_view": 1,
"weight": 10
},
"twingle_event_creation_url": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Creation URL",
"name": "twingle_event_creation_url",
"is_required": 0,
"is_searchable": 0,
"data_type": "String",
"html_type": "Text",
"text_length": 256,
"is_active": 1,
"is_view": 1,
"weight": 11
},
"twingle_event_url_internal": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Internal URL",
"name": "twingle_event_url_internal",
"is_required": 0,
"is_searchable": 0,
"data_type": "String",
"html_type": "Text",
"text_length": 256,
"is_active": 1,
"is_view": 1,
"weight": 12
},
"twingle_event_url_external": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event External URL",
"name": "twingle_event_url_external",
"is_required": 0,
"is_searchable": 0,
"data_type": "String",
"html_type": "Text",
"text_length": 256,
"is_active": 1,
"is_view": 1,
"weight": 13
},
"twingle_event_url_edit_internal": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Edit Internal URL",
"name": "twingle_event_url_edit_internal",
"is_required": 0,
"is_searchable": 0,
"data_type": "String",
"html_type": "Text",
"text_length": 256,
"is_active": 1,
"is_view": 1,
"weight": 14
},
"twingle_event_url_edit_external": {
"custom_group_id": "Twingle_Event_Information",
"label": "Twingle Event Edit External URL",
"name": "twingle_event_url_edit_external",
"is_required": 0,
"is_searchable": 0,
"data_type": "String",
"html_type": "Text",
"text_length": 256,
"is_active": 1,
"is_view": 1,
"weight": 15
},
"twingle_campaign_parent_project_id": {
"custom_group_id": "Twingle_Campaign_Information",
"label": "Parent TwingleProject ID",
"name": "twingle_campaign_parent_project_id",
"is_required": 0,
"is_searchable": 1,
"data_type": "String",
"html_type": "Text",
"text_length": 16,
"is_active": 1,
"is_view": 1,
"weight": 1
},
"twingle_campaign_cid": {
"custom_group_id": "Twingle_Campaign_Information",
"label": "Twingle Campaign CID",
"name": "twingle_campaign_cid",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "Text",
"text_length": 32,
"is_active": 1,
"is_view": 1,
"weight": 2
},
"twingle_campaign_url": {
"custom_group_id": "Twingle_Campaign_Information",
"label": "Twingle Campaign URL",
"name": "twingle_campaign_url",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 600,
"is_active": 1,
"is_view": 1,
"weight": 3
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,13 +0,0 @@
{
"TwingleProject": {
"name": "title",
"last_update": "last_modified_date",
"project_target": "goal_revenue"
},
"TwingleEvent": {
"description": "title",
"updated_at": "last_modified_date",
"created_at": "start_date",
"target": "goal_revenue"
}
}

View file

@ -0,0 +1,18 @@
<?php
return [
"TwingleProject" => [
"name" => "title",
"last_update" => "last_modified_date",
"project_target" => "goal_revenue",
"counter-url" => "counter",
"embed" => "embed_codes"
],
"TwingleEvent" => [
"description" => "title",
"updated_at" => "last_modified_date",
"created_at" => "start_date",
"target" => "goal_revenue"
]
];

View file

@ -1,8 +0,0 @@
{
"twingle_event_donation": {
"name": "twingle_event_donation",
"label": "Twingle Event",
"description": "A soft credit type for TwingleEvent initiators.",
"option_group_id": "soft_credit_type"
}
}

View file

@ -0,0 +1,10 @@
<?php
return [
"twingle_event_donation" => [
"name" => "twingle_event_donation",
"label" => "Twingle Event",
"description" => "A soft credit type for TwingleEvent initiators.",
"option_group_id" => "soft_credit_type"
]
];

View file

@ -1,61 +0,0 @@
{
"TwingleProject": [
"id",
"identifier",
"allow_more",
"name",
"organisation_id",
"project_target",
"transaction_type",
"type",
"last_update",
"url"
],
"project_embed_data": [
"page",
"widget",
"form",
"form-single",
"widget-single",
"eventall",
"eventlist",
"counter"
],
"TwingleEvent": [
"id",
"project_id",
"identifier",
"description",
"user_name",
"user_email",
"is_public",
"deleted",
"confirmed_at",
"created_at",
"updated_at",
"target",
"creation_url",
"show_internal",
"show_external",
"edit_internal",
"edit_external",
"urls"
],
"event_embed_data": [
"page",
"eventpage",
"widget",
"form",
"widget-single",
"form-single",
"eventall",
"eventlist",
"eventeditcreate"
],
"TwingleCampaign": [
"id",
"parent_id",
"name",
"title"
]
}

View file

@ -0,0 +1,114 @@
<?php
return [
"TwingleProject" => [
"project_data" => [
"id",
"identifier",
"allow_more",
"name",
"organisation_id",
"project_target",
"transaction_type",
"type",
"last_update",
"url"
],
"project_embed_data" => [
"page",
"widget",
"form",
"form-single",
"widget-single",
"eventall",
"eventlist",
"counter"
],
"project_options" => [
"has_confirmation_mail",
"has_donation_receipt",
"has_contact_data",
"donation_rhythm",
"default_rhythm",
"has_newsletter_registration",
"has_postinfo_registration",
"design_background_color",
"design_primary_color",
"design_font_color",
"bcc_email_address",
"donation_value_min",
"donation_value_max",
"donation_value_default",
"contact_fields",
"exclude_contact_fields",
"mandatory_contact_fields",
"custom_css",
"share_url",
"has_contact_mandatory",
"has_doi",
"has_force_donation_target_buttons",
"slidericon",
"has_hidden_logo",
"has_projecttarget_as_money",
"has_donationtarget_textfield",
"has_civi_crm_activated",
"has_step_index",
"languages",
"has_buttons",
"has_no_slider",
"buttons",
"has_newsletter_namerequest",
"has_show_donator_data"
],
"payment_methods" => [
"has_paypal",
"has_banktransfer",
"has_debit",
"has_sofortueberweisung",
"has_paypal_recurring",
"has_debit_recurring"
]
],
"TwingleEvent" => [
"event_data" => [
"id",
"project_id",
"identifier",
"description",
"user_name",
"user_email",
"is_public",
"deleted",
"confirmed_at",
"created_at",
"updated_at",
"target",
"creation_url",
"show_internal",
"show_external",
"edit_internal",
"edit_external",
"urls"
],
"event_embed_data" => [
"page",
"eventpage",
"widget",
"form",
"widget-single",
"form-single",
"eventall",
"eventlist",
"eventeditcreate"
]
],
"TwingleCampaign" => [
"campaign_data" => [
"id",
"parent_id",
"name",
"title"
]
]
];

View file

@ -105,11 +105,11 @@ function civicrm_api3_twingle_campaign_Get(array $params): array {
// Get campaign type id for TwingleCampaign
$twingle_campaign_campaign_type_id =
Cache::getInstance()
->getCampaigns()['campaign_types']['twingle_campaign']['id'];
->getCampaignIds()['campaign_types']['twingle_campaign']['id'];
// If no id but a project_id is provided, get all TwingleCampaign children of
// this TwingleProject
if (array_key_exists('project_id', $params) && $params['project_id']) {
// If no id but a parent_id or a project_id is provided, get all
// TwingleCampaign children of this TwingleProject
if (isset($params['project_id']) && !isset($params['parent_id'])) {
// Get TwingleProject
$project = civicrm_api3('TwingleProject',

View file

@ -157,6 +157,7 @@ function civicrm_api3_twingle_event_Get(array $params): array {
$tmp_event = new TwingleEvent([]);
$tmp_event->translateKeys(
$returnValues[$event['id']],
TwingleEvent::EVENT,
TwingleEvent::OUT
);
TwingleEvent::formatValues(

View file

@ -127,7 +127,7 @@ function civicrm_api3_twingle_project_Get(array $params): array {
$query = ['options' => ['limit' => 0]];
foreach ($params as $key => $value) {
if ( $key != 'id' &&
if ($key != 'id' &&
array_key_exists('twingle_project_' . $key, $custom_field_mapping)
) {
$query[$custom_field_mapping['twingle_project_' . $key]] = $value;
@ -156,22 +156,28 @@ function civicrm_api3_twingle_project_Get(array $params): array {
$returnValues[$project['id']][$key] = $value;
}
}
foreach($returnValues[$project['id']] as $key => $value) {
foreach ($returnValues[$project['id']] as $key => $value) {
if ($key != 'twingle_project_id' && strpos($key, 'twingle_project_') === 0) {
$returnValues[$project['id']][str_replace('twingle_project_', '', $key)]
= $value;
$key_short = str_replace('twingle_project_', '', $key);
$returnValues[$project['id']][$key_short] = $value;
unset($returnValues[$project['id']][$key]);
} elseif($key == 'twingle_project_id'){
}
elseif ($key == 'twingle_project_id') {
$returnValues[$project['id']]['project_id'] = $value;
unset($returnValues[$project['id']]['twingle_project_id']);
}
}
try {
$tmp_project = new TwingleProject([]);
$tmp_project->translateKeys($returnValues[$project['id']], TwingleProject::OUT);
$tmp_project->formatValues($returnValues[$project['id']], TwingleProject::OUT);
}
catch (Exception $e) {
TwingleProject::translateKeys(
$returnValues[$project['id']],
TwingleProject::PROJECT,
TwingleProject::OUT
);
TwingleProject::formatValues(
$returnValues[$project['id']],
TwingleProject::OUT
);
} catch (Exception $e) {
throw new API_Exception($e->getMessage());
}
}

View file

@ -104,7 +104,6 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
// instantiate project from CiviCRM
$id = $result['id'];
unset($result['id']);
$project = new TwingleProject($result, $id);
// Synchronize projects
@ -131,6 +130,20 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
// instantiate project
$project = new TwingleProject($result, $id);
// Send project information to Tingle and update project with the
// answer
$projectOptions = $project->getOptions();
$project->deleteOptions();
$paymentMethods = $project->getPaymentMethods();
$project->deletePaymentMethods();
$projectFromTwingle = $twingleApi->pushProject($project->export());
$project = new TwingleProject($projectFromTwingle, $project->getId());
$projectValues = $project->getValues();
$projectValues['project_options'] = $projectOptions;
$projectValues['payment_methods'] = $paymentMethods;
$project->update($projectValues);
$project->complement($projectFromTwingle);
// Push project to Twingle
return _pushProjectToTwingle($project, $twingleApi, $params);
}
@ -140,7 +153,7 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
else {
// Counter for sync errors
$errors_occurred = 0;
$errors = [];
// Get all projects from Twingle
$projects_from_twingle = $twingleApi->getProject();
@ -172,7 +185,7 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
// push project to Twingle
$result = _pushProjectToTwingle($project, $twingleApi, $params);
if ($result['is_error'] != 0) {
$errors_occurred++;
$errors[$result['id']] = $result['error_message'];
$returnValues[$project->getId()] =
$project->getResponse($result['error_message']);
}
@ -189,11 +202,6 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
$project = new TwingleProject($project_from_twingle);
try {
// Get embed data
$project->setEmbedData(
$twingleApi->getProjectEmbedData($project->getProjectId())
);
// If this is a test, do not make db changes
if (isset($params['is_test']) && $params['is_test']) {
$returnValues[$project->getId()] =
@ -204,7 +212,7 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
$returnValues[$project->getId()] =
$project->getResponse('TwingleProject created');
} catch (Exception $e) {
$errors_occurred++;
$errors[$result['id']] = $result['error_message'];
Civi::log()->error(
E::LONG_NAME .
' could not create TwingleProject: ' .
@ -223,22 +231,27 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
foreach ($projects_from_twingle as $project_from_twingle) {
if ($project_from_twingle['id'] == $project_from_civicrm['project_id']) {
// store campaign id in $id
// store campaign id in $id and replace it with project_id
$id = $project_from_civicrm['id'];
unset($project_from_civicrm['id']);
$project_from_civicrm['id'] = $project_from_civicrm['project_id'];
unset($project_from_civicrm['project_id']);
// instantiate project with values from TwingleProject.Get
$project = new TwingleProject($project_from_civicrm, $id);
// sync project
$result = _projectSync($project, $project_from_twingle, $twingleApi, $params);
if ($result['is_error'] != 0) {
$errors_occurred++;
$result = _projectSync(
$project,
$project_from_twingle,
$twingleApi,
$params);
if (!$result['is_error'] == 0) {
$errors[$result['id']] = $result['error_message'];
$returnValues[$project->getId()] =
$project->getResponse($result['error_message']);
}
else {
$returnValues[$project->getId()] = $result['values'];
$returnValues[$result['id']] = $result['values'][$result['id']];
}
break;
}
@ -246,13 +259,29 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
}
// Return results
if ($errors_occurred > 0) {
$errorMessage = ($errors_occurred > 1)
? "$errors_occurred synchronisation processes resulted with an error"
if (sizeof($errors) > 0) {
$errorCount = sizeof($errors);
$errorMessage = ($errorCount > 1)
? "$errorCount synchronisation processes resulted with an error"
: "1 synchronisation process resulted with an error";
// Log errors
Civi::log()->error(E::LONG_NAME . ': ' . $errorMessage, $errors);
// Return API Error
$errorMessage = $errorMessage . ': [';
foreach ($errors as $key => $value) {
$errorMessage =
$errorMessage .
" ['project_id' => '$key', 'error_message' => '$value'],";
}
$errorMessage =
substr($errorMessage, 0, strlen($errorMessage) - 1) . ' ]';
return civicrm_api3_create_error(
$errorMessage,
$returnValues
$errors
);
}
else {
@ -284,13 +313,13 @@ function _updateProjectLocally(array $project_from_twingle,
try {
$project->update($project_from_twingle);
$project->setEmbedData(
$twingleApi->getProjectEmbedData($project->getProjectId())
);
// If this is a test, do not make db changes
if (array_key_exists('is_test', $params) && $params['is_test']) {
$response[$project->getId()] =
$project->getResponse('TwingleProject ready to update');
return civicrm_api3_create_success(
$project->getResponse('TwingleProject ready to update'),
$response,
$params,
'TwingleProject',
'Sync'
@ -298,7 +327,8 @@ function _updateProjectLocally(array $project_from_twingle,
}
// ... else, update local TwingleProject campaign
$project->create(TRUE);
$response = $project->getResponse('TwingleProject updated successfully');
$response[$project->getId()] =
$project->getResponse('TwingleProject updated successfully');
return civicrm_api3_create_success(
$response,
$params,
@ -326,18 +356,22 @@ function _updateProjectLocally(array $project_from_twingle,
* @param \CRM_TwingleCampaign_BAO_TwingleProject $project
* @param \CRM_TwingleCampaign_BAO_TwingleApiCall $twingleApi
* @param array $params
* @param bool $update Update project after push?
*
* @return array
* @throws \CiviCRM_API3_Exception
*/
function _pushProjectToTwingle(TwingleProject $project,
TwingleApiCall $twingleApi,
array $params): array {
array $params = [],
bool $update = TRUE): array {
// If this is a test, do not make db changes
if ($params['is_test']) {
if (isset($params['is_test']) && $params['is_test']) {
$response[$project->getId()] =
$project->getResponse('TwingleProject ready to push to Twingle');
return civicrm_api3_create_success(
$project->getResponse('TwingleProject ready to push to Twingle'),
$response,
$params,
'TwingleProject',
'Sync'
@ -346,7 +380,7 @@ function _pushProjectToTwingle(TwingleProject $project,
// Push project to Twingle
try {
$result = $twingleApi->pushProject($project);
$result = $twingleApi->pushProject($project->export());
} catch (Exception $e) {
Civi::log()->error(
E::LONG_NAME .
@ -361,46 +395,55 @@ function _pushProjectToTwingle(TwingleProject $project,
}
// Update local campaign with data returning from Twingle
if ($result) {
$project->update($result);
// Get embed data
try {
$project->setEmbedData(
$twingleApi->getProjectEmbedData($project->getProjectId())
);
// Create updated campaign
$project->create(TRUE);
$response = $project->getResponse('TwingleProject pushed to Twingle');
return civicrm_api3_create_success(
$response,
$params,
'TwingleProject',
'Sync'
);
} catch (Exception $e) {
if ($update) {
if ($result) {
$project->update($result);
try {
// Create updated campaign
$project->create(TRUE);
$response[$project->getId()] =
$project->getResponse('TwingleProject pushed to Twingle');
return civicrm_api3_create_success(
$response,
$params,
'TwingleProject',
'Sync'
);
} catch (Exception $e) {
Civi::log()->error(
E::LONG_NAME .
' pushed TwingleProject to Twingle but local update failed: ' .
$e->getMessage(),
$project->getResponse()
);
return civicrm_api3_create_error(
'TwingleProject was pushed to Twingle but local update failed: ' .
$e->getMessage(),
$project->getResponse()
);
}
}
// If the curl fails, the $result may be empty
else {
Civi::log()->error(
E::LONG_NAME .
' pushed TwingleProject to Twingle but local update failed: ' .
$e->getMessage(),
' could not push TwingleProject campaign',
$project->getResponse()
);
return civicrm_api3_create_error(
'TwingleProject was pushed to Twingle but local update failed: ' .
$e->getMessage(),
"Could not push TwingleProject campaign",
$project->getResponse()
);
}
}
// If the curl fails, the $result may be empty
else {
Civi::log()->error(
E::LONG_NAME .
' could not push TwingleProject campaign',
$project->getResponse()
);
return civicrm_api3_create_error(
"Could not push TwingleProject campaign",
$project->getResponse()
$response[$project->getId()] =
$project->getResponse('TwingleProject pushed to Twingle');
return civicrm_api3_create_success(
$response,
$params,
'TwingleProject',
'Sync'
);
}
}
@ -432,12 +475,24 @@ function _projectSync(TwingleProject $project,
// If the CiviCRM TwingleProject campaign was changed, update the project
// on Twingle's side
elseif ($project_from_twingle['last_update'] < $project->lastUpdate()) {
// Make sure that the project hast a correct project_id. This is important
// to avoid an accidental cloning of project.
if (empty($project->getProjectId())) {
throw new \CiviCRM_API3_Exception(
'Missing project_id for project that is meant to get updated on Twingle side.');
}
// By merging the project values with the values coming from Twingle, we
// make sure that the project contains all values needed to get pushed
$project->complement($project_from_twingle);
return _pushProjectToTwingle($project, $twingleApi, $params);
}
// If both versions are still synchronized
else {
$response = $project->getResponse('TwingleProject up to date');
$response[$project->getId()] =
$project->getResponse('TwingleProject up to date');
return civicrm_api3_create_success(
$response,
$params,

34
docs/Twingle_Project.md Normal file
View file

@ -0,0 +1,34 @@
# Twingle Project
This campaign type represents Twingle donation forms. *Twingle Projects* are campaigns which get synchronized between
Twingle and your CiviCRM instance in both directions. A *Twingle Project* has three extra sections:
## Twingle Information
This section shows the external Twingle id, the identifier and the project type (default, event or membership). You can
change the project type at any time, but please be aware that your Twingle donation forms will change their appearance
depending on what project type is selevted.
## Twingle Settings
Here you can find almost all settings to configure a donation form. Each setting has a help text.
Currently, there is no front end input validation but all settings get validated on server side when the form gets
saved. If the validation fails, an error message will be displayed that contains further information. In this case, the
form won't get saved.
## Twingle Payment Methods
These settings allow you to specify the payment methods that you want to offer to users for one time and recurring
donations.
Currently, the extension only supports to configure *PayPal*, *bank transfer*, *debit* and *Sofortüberweisung* as one
time payment methods and *PayPal* and *debit* as recurring payment methods. This may be enhanced in future versions.
Nevertheless, you can configure additional payment methods in the *[TwingleMANAGER](https://twinglemanager.de)* they
won't get overwritten by the *Twingle Campaign* extension.
Please make sure to establish all payment methods in your general *[TwingleMANAGER](https://twinglemanager.de)* settings
before you try to configure them for *Twingle Projects*.
## Twingle Project Preview
![TwingleProject](../images/TwingleProject_settings.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

View file

@ -12,6 +12,48 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: de_DE\n"
#: CRM/TwingleCampaign/BAO/CustomField.php
msgid ""
"Creation of custom field '%1' failed. Find more information in the logs."
msgstr ""
"Erstellung von Custom Field '%1' fehlgeschlagen. Mehr Informationen in den "
"Logs."
#: CRM/TwingleCampaign/BAO/CustomField.php
msgid "Creation of custom field failed. Find more information in the logs."
msgstr ""
"Erstellung von Custom Field '%1' fehlgeschlagen. Mehr Informationen in den "
"Logs."
#: CRM/TwingleCampaign/BAO/CustomField.php
msgid ""
"Creation of custom field '%1' failed, because a custom field with that name "
"already exists. Find more information in the logs."
msgstr ""
"Erstellung der Custom Field '%1' fehlgeschlagen, weil bereits eine Custom "
"Field mit selbem Namen existiert. Mehr Informationen in den Logs."
#: CRM/TwingleCampaign/BAO/CustomGroup.php
msgid ""
"Creation of custom group '%1' failed. Find more information in the logs."
msgstr ""
"Erstellung von Custom Field '%1' fehlgeschlagen. Mehr Informationen in den "
"Logs."
#: CRM/TwingleCampaign/BAO/CustomGroup.php
msgid "Creation of custom group failed. Find more information in the logs."
msgstr ""
"Erstellung von Custom Field '%1' fehlgeschlagen. Mehr Informationen in den "
"Logs."
#: CRM/TwingleCampaign/BAO/CustomGroup.php
msgid ""
"Creation of custom group '%1' failed, because a custom group with that name "
"already exists. Find more information in the logs."
msgstr ""
"Erstellung der Custom Group '%1' fehlgeschlagen, weil bereits eine Custom "
"Group mit selbem Namen existiert. Mehr Informationen in den Logs."
#: CRM/TwingleCampaign/BAO/TwingleCampaign.php
msgid ""
"Could not determine parent TwingleProject URL. This URL is needed to create "
@ -36,6 +78,37 @@ msgstr ""
msgid "No parent TwingleProject found"
msgstr "Kein übergeordnetes TwingleProjekt gefunden"
#: CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "BCC email invalid"
msgstr "BCC-Email-Adresse ungültig"
#: CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Invalid hexadecimal value in color field: %1"
msgstr "Ungültige Hexadezimalzahl in Farbfeld: %1"
#: CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Missing maximum donation value"
msgstr "Maximale Spendenhöhe fehlt"
#: CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Maximum donation value must be higher than the minimum"
msgstr "Die maximale Spendenhöhe muss höher als die minimale sein"
#: CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Default donation value must lie in between maximum and minimum values"
msgstr ""
"Die voreingestellte Spendenhöhe muss zwischen Minimum und Maximum liegen"
#: CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Donation values (Min, Max, Default) must be positive integers"
msgstr ""
"Die minimale, maximale und die voreingestellte Spendenhöhe müssen positive "
"Ganzzahlen sein"
#: CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Invalid URL: %1"
msgstr "Ungültige URL: %1"
#: CRM/TwingleCampaign/Form/Settings.php api/v3/TwingleEvent/Delete.php
#: api/v3/TwingleEvent/Sync.php api/v3/TwingleProject/Delete.php
#: api/v3/TwingleProject/Sync.php api/v3/TwingleSync/Sync.php
@ -109,6 +182,664 @@ msgstr ""
msgid "Could not disable scheduled job \"TwingleSync\"."
msgstr "Geplante Aufgabe \"TwingleSync\" konnte nicht deaktiviert werden."
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Information"
msgstr "Twingle Informationen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Settings"
msgstr "Twingle Einstellungen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Payment Methods"
msgstr "Twingle Zahlungsarten"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Embed Codes"
msgstr "Twingle Embed Codes"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Event Information"
msgstr "Twingle Event Informationen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Campaign Information"
msgstr "Twingle Campaign Informationen"
#: CRM/TwingleCampaign/resources/campaigns.php api/v3/TwingleEvent/Delete.php
#: api/v3/TwingleEvent/Get.php api/v3/TwingleEvent/Getsingle.php
#: api/v3/TwingleEvent/Sync.php api/v3/TwingleProject/Create.php
#: api/v3/TwingleProject/Delete.php api/v3/TwingleProject/Get.php
#: api/v3/TwingleProject/Getsingle.php api/v3/TwingleProject/Sync.php
msgid "Twingle Project ID"
msgstr "Twingle Project ID"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Organisation ID"
msgstr "Organisations ID"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "identifier"
msgstr "Kennung"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "An unique identifier for a project (auto generated)"
msgstr "Eindeutige Kennung eines Projekts (automatisch generiert)"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Type"
msgstr "Typ"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Default"
msgstr "Default"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Events"
msgstr "Events"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Membership"
msgstr "Mitgliedschaft"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid ""
"Choose the project type. Allow users to create own events or to pay a "
"membership fee."
msgstr ""
"Wähle den Projekt-Typ: erlaube Benutzern ihre eigenen Spenden-Events "
"anzulegen oder eine Mitgliedschaft zu bezahlen."
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "allow more"
msgstr "Mehr zulassen"
#: CRM/TwingleCampaign/resources/campaigns.php api/v3/TwingleProject/Create.php
#: api/v3/TwingleProject/Get.php api/v3/TwingleProject/Getsingle.php
msgid "Allow to donate more than is defined in the target"
msgstr "Zulassen, dass mehr gespendet wird als im Spendenziel angegeben ist"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "transaction type"
msgstr "Transaktionstyp"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "URL"
msgstr "URL"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Widget"
msgstr "Widget"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Form"
msgstr "Formular"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Widget Single"
msgstr "Einzelnes Widget"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Form Single"
msgstr "Formular Widget"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "All Events"
msgstr "Alle Events"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Event List"
msgstr "Event-Liste"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Counter"
msgstr "Zähler"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Page"
msgstr "Seite"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Confirmation Mail"
msgstr "Bestätigungsmail"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Send confirmation mail"
msgstr "Sende Bestätigungs-E-Mail"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Receipt"
msgstr "Spendenbescheinigung"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Offer donation receipts"
msgstr "Biete Spendenbescheinigungen an"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Contact Data"
msgstr "Kontaktdaten"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Rhythm"
msgstr "Spendenrhythmus"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "yearly"
msgstr "jährlich"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "halfyearly"
msgstr "halbjährlich"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "quarterly"
msgstr "vierteljährlich"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "monthly"
msgstr "monatlich"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "one time"
msgstr "einmalig"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid ""
"The selected options are available for selection in the donation widget."
msgstr "Die ausgewählten Optionen stehen im Spenden-Widget zur Verfügung"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Default Rhythm"
msgstr "Standard Spendenrhythmus"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Which donation rhythm should be displayed as selected by default?"
msgstr "Welcher Spendenrhythmus soll standardmäßig ausgewählt sein?"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Newsletter Registration"
msgstr "Newsletter-Registrierung"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Enable newsletter registration"
msgstr "Registrierung für Newsletter aktivieren"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Postinfo Registration"
msgstr "Postinfo-Registrierung"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Enable post info registration"
msgstr "Registrierung für Postinfos aktivieren"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Background Color"
msgstr "Hintergrundfarbe"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Hex color code (e.g. ffffff for white)"
msgstr "Hex-Farbcode (z.B. ffffff für weiß)"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Primary Color"
msgstr "Primärfarbe"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Font Color"
msgstr "Schriftfarbe"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "BCC Email"
msgstr "BCC-E-Mail"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid ""
"Email address used as bcc addresses for confirmation mail which is send to "
"an user"
msgstr "E-Mail-Adresse für den BBC beim Versenden der Bestätigungs-E-Mail"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Min"
msgstr "Spendenminimum"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Minimum donation value"
msgstr "Mindestspendenbetrag"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Max"
msgstr "Spendenmaximum"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Maximum donation value"
msgstr "Höchstspendenbetrag"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Default"
msgstr "Standardspendenhöhe"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Default donation value"
msgstr "Standardspendenbetrag"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Contact Fields"
msgstr "Kontaktfelder"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Salutation"
msgstr "Anrede"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "First name"
msgstr "Vorname"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Last name"
msgstr "Nachname"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Company"
msgstr "Firma"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Birthday"
msgstr "Geburtsdatum"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Street"
msgstr "Straße"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Postal Code"
msgstr "Postleitzahl"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "City"
msgstr "Stadt"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Country"
msgstr "Land"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Telephone"
msgstr "Telefon"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Fields to include in contact form"
msgstr "Felder für Kontaktformular"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Mandatory Contact Fields"
msgstr "Pflicht-Kontaktfelder"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Fields that must get filled in the contact form."
msgstr "Pflichtfelder für Kontaktformular"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Custom CSS"
msgstr "Benutzerdefiniertes CSS"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "URL to a custom CSS file that will be included in the frontend"
msgstr ""
"URL einer benutzerdefinierten CSS-Datei, die im Frontend eingebunden wird"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Share URL"
msgstr "Teilen-URL"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "URL for the sharing component on the last page and doi page"
msgstr "URL für Teilen-Elemente auf der letzten Seite und auf der DOI-Seite"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Contact Mandatory"
msgstr "Kontaktdaten sind Pflicht"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "If the contact data should be requested mandatory as second step"
msgstr "Die Kontaktdaten als Pflichtangaben im zweiten Schritt abfragen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Double Opt-In"
msgstr "Doppeltes Opt-In"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid ""
"Enable Twingle's double opt-in (Do not enable, if you use CiviCRM's double "
"opt-in!)"
msgstr ""
"Tingles doppelten Opt-In aktivieren (Nicht aktivieren, wenn der doppelte Opt-"
"In von CiviCRM verwendet wird!)"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Force Donation Taget as Button"
msgstr "Spendenziel-Knopf erzwingen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Force showing the donation targets as buttons"
msgstr "Erzwingen der Anzeige der Spendenziele als Knöpfe"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Slider Icon"
msgstr "Icon für Schieberegler"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Heart"
msgstr "Herz"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Asterisk"
msgstr "Sternchen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Animal"
msgstr "Pfote"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Lifebelt"
msgstr "Rettungsring"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Angellist"
msgstr "Peace-Hand"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Handshake"
msgstr "Handschütteln"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Dollar"
msgstr "Dollar"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Menue"
msgstr "Menübalken"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Office"
msgstr "Büro"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Leaf"
msgstr "Blatt"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Cog"
msgstr "Zahnrad"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "SVG"
msgstr "SVG"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Euro"
msgstr "Euro"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Stats"
msgstr "Statistik"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Circle"
msgstr "Kreis"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Water drop outline"
msgstr "Wassertropfen (Umriss)"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Water drop"
msgstr "Wassertropfen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Gift"
msgstr "Geschenk"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Bee"
msgstr "Biene"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Flower"
msgstr "Blume"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Train"
msgstr "Zug"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "No Icon"
msgstr "Kein Icon"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Hidden Logo"
msgstr "Verstecktes Logo"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Hide the Logo on the project page"
msgstr "Verstecke das Logo auf der Projektseite"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Target Format"
msgstr "Spendenzielformat in Euro"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Format of the reached portion of the donation target"
msgstr "Format des Spendenstands"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Purpose as Textfield"
msgstr "Spendenzweck als Textfeld"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Let donors enter their own donation purpose"
msgstr "Erlaubt Spendern, ihre eigenen Spendenzwecke einzutragen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Activate CiviCRM Support"
msgstr "CiviCRM-Unterstützung aktivieren"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Activate support for Twingle Extension (de.systopia.twingle)"
msgstr ""
"Aktiviert die Unterstützung für die Twingle-Erweiterung (de.systopia.twingle)"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Show Step Index"
msgstr "Zeige Fortschrittsanzeige"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Show a step index during donation process"
msgstr "Fortschrittsanzeige beim Spendenprozess anzeigen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Languages"
msgstr "Sprachen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "German"
msgstr "Deutsch"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "English"
msgstr "Englisch"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "French"
msgstr "Französisch"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Spanish"
msgstr "Spanisch"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Buttons"
msgstr "Knöpfe"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid ""
"Up to four buttons can be configured. If you leave the amount blank, the "
"button will not be displayed."
msgstr ""
"Bis zu vier Knöpfe können konfiguriert werden. Wenn Sie den Wert frei "
"lassen, wird der Knopf nicht angezeigt."
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Slider"
msgstr "Schieberegler"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Show a slider that allows the donor to choose the donation amount."
msgstr ""
"Zeige einen Schieberegler, der es dem Spender erlaubt, einen Betrag zu wählen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Button 1"
msgstr "Knopf 1"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Amount to be displayed on Button 1"
msgstr "Betrag der auf Knopf 1 angezeigt wird"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Button 2"
msgstr "Knopf 2"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Amount to be displayed on Button 2"
msgstr "Betrag der auf Knopf 2 angezeigt wird"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Button 3"
msgstr "Knopf 3"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Amount to be displayed on Button 3"
msgstr "Betrag der auf Knopf 3 angezeigt wird"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Button 4"
msgstr "Knopf 4"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Amount to be displayed on Button 4"
msgstr "Betrag der auf Knopf 4 angezeigt wird"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Newsletter Name Requested"
msgstr "Name für Newsletter abfragen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Must a donor give his name for newsletter sign-up?"
msgstr ""
"Muss ein Spender seinen Namen für die Newsletter-Registrierung angeben?"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Show List of Donations"
msgstr "Spendenliste anzeigen"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Display a list of public donations"
msgstr "Zeigt eine liste öffentlicher Spenden an"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Payment Methods"
msgstr "Zahlungsarten"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "PayPal"
msgstr "PayPal"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Banktransfer"
msgstr "Banküberweisung"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Debit"
msgstr "Bankeinzug"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Sofortüberweisung"
msgstr "Sofortüberweisung"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid ""
"Chose which payment methods should be available. NOTE: You might have to "
"activate them first in the Twingle-Manager configuration."
msgstr ""
"Wählen Sie aus, welche Zahlungsarten verfügbar sein sollen. WICHTIG: Sie "
"müssen die Zahlungsarten eventuell erst im Twingle-Manager konfigurieren."
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Recurring Payment Methods"
msgstr "Wiederkehrende Zahlungsarten"
#: CRM/TwingleCampaign/resources/campaigns.php api/v3/TwingleEvent/Delete.php
#: api/v3/TwingleEvent/Get.php api/v3/TwingleEvent/Getsingle.php
#: api/v3/TwingleEvent/Sync.php
msgid "Twingle Event ID"
msgstr "Twingle Event ID"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Identifier"
msgstr "Kennung"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Initiator"
msgstr "Initiator"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Initiator Email"
msgstr "Initiator E-Mail"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Is public"
msgstr "Ist öffentlich"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Deleted"
msgstr "Gelöscht"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Confirmed At"
msgstr "Bestätigt am"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Created At"
msgstr "Erstellt am"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Creation URL"
msgstr "Erstell-URL"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Internal URL"
msgstr "Interne URL"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "External URL"
msgstr "Externe URL"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Edit Internal URL"
msgstr "Interne Bearbeitungs-URL"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Edit External URL"
msgstr "Externe Bearbeitungs-URL"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "Parent TwingleProject ID"
msgstr "Twingle ID des Eltern-TwingleProject"
#: CRM/TwingleCampaign/resources/campaigns.php
msgid "CID"
msgstr "CID"
#: api/v3/TwingleCampaign/Create.php api/v3/TwingleCampaign/Delete.php
#: api/v3/TwingleCampaign/Get.php api/v3/TwingleCampaign/Getsingle.php
#: api/v3/TwingleCampaign/Sync.php
@ -231,7 +962,7 @@ msgstr "Ist diese Kampagne aktiviert oder deaktiviert/abgesagt?"
msgid ""
"A unique identifier for a TwingleCampaign generated by a hashing its id + "
"name"
msgstr ""
msgstr "Einmalige Kennung einer TwingleCampaign"
#: api/v3/TwingleEvent/Delete.php api/v3/TwingleEvent/Get.php
#: api/v3/TwingleEvent/Getsingle.php api/v3/TwingleEvent/Sync.php
@ -247,25 +978,12 @@ msgstr "Kampagnen ID"
msgid "Unique Campaign ID"
msgstr "Einzigartige Kampagnen ID"
#: api/v3/TwingleEvent/Delete.php api/v3/TwingleEvent/Get.php
#: api/v3/TwingleEvent/Getsingle.php api/v3/TwingleEvent/Sync.php
#: api/v3/TwingleProject/Create.php api/v3/TwingleProject/Delete.php
#: api/v3/TwingleProject/Get.php api/v3/TwingleProject/Getsingle.php
#: api/v3/TwingleProject/Sync.php
msgid "Twingle Project ID"
msgstr "Twingle Project ID"
#: api/v3/TwingleEvent/Delete.php api/v3/TwingleEvent/Sync.php
#: api/v3/TwingleProject/Delete.php api/v3/TwingleProject/Get.php
#: api/v3/TwingleProject/Getsingle.php api/v3/TwingleProject/Sync.php
msgid "Twingle ID for this project"
msgstr "Twingle ID dieses Projekts"
#: api/v3/TwingleEvent/Delete.php api/v3/TwingleEvent/Get.php
#: api/v3/TwingleEvent/Getsingle.php api/v3/TwingleEvent/Sync.php
msgid "Twingle Event ID"
msgstr "Twingle Event ID"
#: api/v3/TwingleEvent/Delete.php api/v3/TwingleEvent/Get.php
#: api/v3/TwingleEvent/Getsingle.php api/v3/TwingleEvent/Sync.php
msgid "Twingle ID for this Event"
@ -380,11 +1098,6 @@ msgstr "Typ des Twingle Projects"
msgid "Allow more"
msgstr "Mehr zulassen"
#: api/v3/TwingleProject/Create.php api/v3/TwingleProject/Get.php
#: api/v3/TwingleProject/Getsingle.php
msgid "Allow to donate more than is defined in the target"
msgstr "Zulassen, dass mehr gespendet wird als im Spendenziel angegeben ist"
#: api/v3/TwingleProject/Create.php
msgid "Project Target"
msgstr "Spendenziel"
@ -416,3 +1129,31 @@ msgstr "Allgemeine Einstellungen"
#: templates/CRM/TwingleCampaign/Form/Settings.tpl
msgid "Twingle Event Settings"
msgstr "Twingle Event Einstellungen"
#: twinglecampaign.php
msgid "Campaign cloning failed"
msgstr "Klonen der Kampagne fehlgeschlagen"
#: twinglecampaign.php
msgid "TwingleCampaign update failed"
msgstr "TwingleCampaign-Update fehlgeschlagen"
#: twinglecampaign.php
msgid "TwingleCampaign was saved."
msgstr "TwingleCampaign wurde gespeichert"
#: twinglecampaign.php
msgid "TwingleProject creation failed"
msgstr "Erstellung des TwingleProjects fehlgeschlagen"
#: twinglecampaign.php
msgid "Could not retrieve Twingle API key"
msgstr "Twingle-API-Schlüssel nicht gefunden"
#: twinglecampaign.php
msgid "TwingleProject synchronization failed: %1"
msgstr "Synchronisation des TwingleProjects fehlgeschlagen: %1"
#: twinglecampaign.php
msgid "Input validation failed"
msgstr "Eingabeüberprüfung fehlgeschlagen"

View file

@ -1,3 +1,27 @@
#: ./CRM/TwingleCampaign/BAO/CustomField.php
msgid "Creation of custom field '%1' failed. Find more information in the logs."
msgstr ""
#: ./CRM/TwingleCampaign/BAO/CustomField.php
msgid "Creation of custom field failed. Find more information in the logs."
msgstr ""
#: ./CRM/TwingleCampaign/BAO/CustomField.php
msgid "Creation of custom field '%1' failed, because a custom field with that name already exists. Find more information in the logs."
msgstr ""
#: ./CRM/TwingleCampaign/BAO/CustomGroup.php
msgid "Creation of custom group '%1' failed. Find more information in the logs."
msgstr ""
#: ./CRM/TwingleCampaign/BAO/CustomGroup.php
msgid "Creation of custom group failed. Find more information in the logs."
msgstr ""
#: ./CRM/TwingleCampaign/BAO/CustomGroup.php
msgid "Creation of custom group '%1' failed, because a custom group with that name already exists. Find more information in the logs."
msgstr ""
#: ./CRM/TwingleCampaign/BAO/TwingleCampaign.php
msgid "Could not determine parent TwingleProject URL. This URL is needed to create the TwingleEvent URL. Please check the logs."
msgstr ""
@ -14,6 +38,34 @@ msgstr ""
msgid "No parent TwingleProject found"
msgstr ""
#: ./CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "BCC email invalid"
msgstr ""
#: ./CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Invalid hexadecimal value in color field: %1"
msgstr ""
#: ./CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Missing maximum donation value"
msgstr ""
#: ./CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Maximum donation value must be higher than the minimum"
msgstr ""
#: ./CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Default donation value must lie in between maximum and minimum values"
msgstr ""
#: ./CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Donation values (Min, Max, Default) must be positive integers"
msgstr ""
#: ./CRM/TwingleCampaign/BAO/TwingleProject.php
msgid "Invalid URL: %1"
msgstr ""
#: ./CRM/TwingleCampaign/Form/Settings.php ./api/v3/TwingleEvent/Delete.php ./api/v3/TwingleEvent/Sync.php ./api/v3/TwingleProject/Delete.php ./api/v3/TwingleProject/Sync.php ./api/v3/TwingleSync/Sync.php
msgid "Twingle API key"
msgstr ""
@ -74,6 +126,634 @@ msgstr ""
msgid "Could not disable scheduled job \"TwingleSync\"."
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Information"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Settings"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Payment Methods"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Embed Codes"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Event Information"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Twingle Campaign Information"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php ./api/v3/TwingleEvent/Delete.php ./api/v3/TwingleEvent/Get.php ./api/v3/TwingleEvent/Getsingle.php ./api/v3/TwingleEvent/Sync.php ./api/v3/TwingleProject/Create.php ./api/v3/TwingleProject/Delete.php ./api/v3/TwingleProject/Get.php ./api/v3/TwingleProject/Getsingle.php ./api/v3/TwingleProject/Sync.php
msgid "Twingle Project ID"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Organisation ID"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "identifier"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "An unique identifier for a project (auto generated)"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Type"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Default"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Events"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Membership"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Choose the project type. Allow users to create own events or to pay a membership fee."
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "allow more"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php ./api/v3/TwingleProject/Create.php ./api/v3/TwingleProject/Get.php ./api/v3/TwingleProject/Getsingle.php
msgid "Allow to donate more than is defined in the target"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "transaction type"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "URL"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Widget"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Form"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Widget Single"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Form Single"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "All Events"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Event List"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Counter"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Page"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Confirmation Mail"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Send confirmation mail"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Receipt"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Offer donation receipts"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Contact Data"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Rhythm"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "yearly"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "halfyearly"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "quarterly"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "monthly"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "one time"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "The selected options are available for selection in the donation widget."
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Default Rhythm"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Which donation rhythm should be displayed as selected by default?"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Newsletter Registration"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Enable newsletter registration"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Postinfo Registration"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Enable post info registration"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Background Color"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Hex color code (e.g. ffffff for white)"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Primary Color"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Font Color"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "BCC Email"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Email address used as bcc addresses for confirmation mail which is send to an user"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Min"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Minimum donation value"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Max"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Maximum donation value"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Default"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Default donation value"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Contact Fields"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Salutation"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "First name"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Last name"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Company"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Birthday"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Street"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Postal Code"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "City"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Country"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Telephone"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Fields to include in contact form"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Mandatory Contact Fields"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Fields that must get filled in the contact form."
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Custom CSS"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "URL to a custom CSS file that will be included in the frontend"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Share URL"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "URL for the sharing component on the last page and doi page"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Contact Mandatory"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "If the contact data should be requested mandatory as second step"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Double Opt-In"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Enable Twingle's double opt-in (Do not enable, if you use CiviCRM's double opt-in!)"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Force Donation Taget as Button"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Force showing the donation targets as buttons"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Slider Icon"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Heart"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Asterisk"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Animal"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Lifebelt"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Angellist"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Handshake"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Dollar"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Menue"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Office"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Leaf"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Cog"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "SVG"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Euro"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Stats"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Circle"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Water drop outline"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Water drop"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Gift"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Bee"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Flower"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Train"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "No Icon"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Hidden Logo"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Hide the Logo on the project page"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Target Format"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Format of the reached portion of the donation target"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Donation Purpose as Textfield"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Let donors enter their own donation purpose"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Activate CiviCRM Support"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Activate support for Twingle Extension (de.systopia.twingle)"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Show Step Index"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Show a step index during donation process"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Languages"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "German"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "English"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "French"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Spanish"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Buttons"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Up to four buttons can be configured. If you leave the amount blank, the button will not be displayed."
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Slider"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Show a slider that allows the donor to choose the donation amount."
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Button 1"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Amount to be displayed on Button 1"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Button 2"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Amount to be displayed on Button 2"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Button 3"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Amount to be displayed on Button 3"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Button 4"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Amount to be displayed on Button 4"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Newsletter Name Requested"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Must a donor give his name for newsletter sign-up?"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Show List of Donations"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Display a list of public donations"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Payment Methods"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "PayPal"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Banktransfer"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Debit"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Sofortüberweisung"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Chose which payment methods should be available. NOTE: You might have to activate them first in the Twingle-Manager configuration."
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Recurring Payment Methods"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php ./api/v3/TwingleEvent/Delete.php ./api/v3/TwingleEvent/Get.php ./api/v3/TwingleEvent/Getsingle.php ./api/v3/TwingleEvent/Sync.php
msgid "Twingle Event ID"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Identifier"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Initiator"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Initiator Email"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Is public"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Deleted"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Confirmed At"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Created At"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Creation URL"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Internal URL"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "External URL"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Edit Internal URL"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Edit External URL"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "Parent TwingleProject ID"
msgstr ""
#: ./CRM/TwingleCampaign/resources/campaigns.php
msgid "CID"
msgstr ""
#: ./api/v3/TwingleCampaign/Create.php ./api/v3/TwingleCampaign/Delete.php ./api/v3/TwingleCampaign/Get.php ./api/v3/TwingleCampaign/Getsingle.php ./api/v3/TwingleCampaign/Sync.php
msgid "Twingle Campaign ID"
msgstr ""
@ -178,18 +858,10 @@ msgstr ""
msgid "Unique Campaign ID"
msgstr ""
#: ./api/v3/TwingleEvent/Delete.php ./api/v3/TwingleEvent/Get.php ./api/v3/TwingleEvent/Getsingle.php ./api/v3/TwingleEvent/Sync.php ./api/v3/TwingleProject/Create.php ./api/v3/TwingleProject/Delete.php ./api/v3/TwingleProject/Get.php ./api/v3/TwingleProject/Getsingle.php ./api/v3/TwingleProject/Sync.php
msgid "Twingle Project ID"
msgstr ""
#: ./api/v3/TwingleEvent/Delete.php ./api/v3/TwingleEvent/Sync.php ./api/v3/TwingleProject/Delete.php ./api/v3/TwingleProject/Get.php ./api/v3/TwingleProject/Getsingle.php ./api/v3/TwingleProject/Sync.php
msgid "Twingle ID for this project"
msgstr ""
#: ./api/v3/TwingleEvent/Delete.php ./api/v3/TwingleEvent/Get.php ./api/v3/TwingleEvent/Getsingle.php ./api/v3/TwingleEvent/Sync.php
msgid "Twingle Event ID"
msgstr ""
#: ./api/v3/TwingleEvent/Delete.php ./api/v3/TwingleEvent/Get.php ./api/v3/TwingleEvent/Getsingle.php ./api/v3/TwingleEvent/Sync.php
msgid "Twingle ID for this Event"
msgstr ""
@ -286,10 +958,6 @@ msgstr ""
msgid "Allow more"
msgstr ""
#: ./api/v3/TwingleProject/Create.php ./api/v3/TwingleProject/Get.php ./api/v3/TwingleProject/Getsingle.php
msgid "Allow to donate more than is defined in the target"
msgstr ""
#: ./api/v3/TwingleProject/Create.php
msgid "Project Target"
msgstr ""
@ -322,3 +990,31 @@ msgstr ""
msgid "Twingle Event Settings"
msgstr ""
#: ./twinglecampaign.php
msgid "Campaign cloning failed"
msgstr ""
#: ./twinglecampaign.php
msgid "TwingleCampaign update failed"
msgstr ""
#: ./twinglecampaign.php
msgid "TwingleCampaign was saved."
msgstr ""
#: ./twinglecampaign.php
msgid "TwingleProject creation failed"
msgstr ""
#: ./twinglecampaign.php
msgid "Could not retrieve Twingle API key"
msgstr ""
#: ./twinglecampaign.php
msgid "TwingleProject synchronization failed: %1"
msgstr ""
#: ./twinglecampaign.php
msgid "Input validation failed"
msgstr ""

View file

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" syntaxCheck="false" bootstrap="tests/phpunit/bootstrap.php">
<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="false" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" syntaxCheck="false" bootstrap="tests/phpunit/bootstrap.php">
<testsuites>
<testsuite name="My Test Suite">
<testsuite name="TwingleCampaign Suite">
<directory>./tests/phpunit</directory>
</testsuite>
</testsuites>

View file

@ -0,0 +1,142 @@
<?php
use CRM_TwingleCampaign_ExtensionUtil as E;
use Civi\Test\HeadlessInterface;
use Civi\Test\HookInterface;
use Civi\Test\TransactionalInterface;
use CRM_TwingleCampaign_BAO_TwingleProject as TwingleProject;
use \Civi\Test\Api3TestTrait;
/**
* # Collection of tests for the TwingleProject class
*
* - tests the full TwingleProject circle (from Twingle to database to Twingle)
* - tests the input validation
*
* @group headless
*/
class CRM_TwingleCampaign_BAO_TwingleProjectTest extends \PHPUnit\Framework\TestCase implements HeadlessInterface, HookInterface, TransactionalInterface {
private $project;
private $dummyProject;
private $badDummyProject;
public function setUpHeadless() {
// Civi\Test has many helpers, like install(), uninstall(), sql(), and sqlFile().
// See: https://docs.civicrm.org/dev/en/latest/testing/phpunit/#civitest
return \Civi\Test::headless()
->installMe(__DIR__)
->apply();
}
/**
* @throws \Exception
*/
public function setUp() {
// Create project from dummy values
$this->dummyProject =
require(E::path() . '/tests/resources/twingle_project_dummy.php');
$this->badDummyProject =
require(E::path() . '/tests/resources/twingle_project_bad_dummy.php');
$this->project = new TwingleProject($this->dummyProject);
$this->project->create(TRUE);
parent::setUp();
}
/**
* @throws \CiviCRM_API3_Exception
*/
public function tearDown() {
// Delete project
$this->project->delete();
unset($this->project);
parent::tearDown();
}
/**
* ## The full TwingleProject circle
* This test simulates a TwingleProject that is fetched from the database and
* than gets instantiated and sent back to Twingle.
*
* It is important that all project values sent to the Twingle API have the
* same data types like when they were retrieved from Twingle. To test this,
* the export array will be compared to the original dummy array.
*
* dummy:array -> project:object -> database -> project:object -> export:array
*
* @throws \CiviCRM_API3_Exception
* @throws \Exception
*/
public function testFullTwingleProjectCircle() {
// Get project via API from database
$project = civicrm_api3(
'TwingleProject',
'getsingle',
['id' => $this->project->getId()]);
$project = new TwingleProject($project, $project['id']);
// Complement project values with dummy values. This is important because
// not all values coming from the Twingle API are stored in the database,
// but the Twingle API requires that all parameters are set.
$project->complement($this->dummyProject);
// Export project
$export = $project->export();
// Check if the project is sent to Twingle in the same state it arrived
$this->assertEquals(
$this->dummyProject,
$export,
'Export values differ from import values.'
);
}
/**
* ## Input validation
* Checks if the input validation works properly.
*
* @throws \CiviCRM_API3_Exception
* @throws \Exception
*/
public function testInputValidation() {
// Get project via API from database
$project = civicrm_api3(
'TwingleProject',
'getsingle',
['id' => $this->project->getId()]);
$project = new TwingleProject($project, $project['id']);
// Check if validation successes with healthy input
$validation_success = $project->validate();
$this->assertTrue(
$validation_success['valid'],
'Validation failed with healthy inputs.'
);
// Update project with values which simulate incorrect user input
$project->update($this->badDummyProject);
// Run validation again
$validation_fail = $project->validate();
// Check if validation failed (as it should)
$this->assertFalse(
$validation_fail['valid'],
'Validation did not fail as expected.'
);
// Check if all 6 wrong inputs were found
$this->assertCount(
6, $validation_fail['messages'],
'Did not find all 6 wrong inputs.'
);
}
}

View file

@ -0,0 +1,136 @@
<?php
return [
"id" => 2243,
"internal_id" => NULL,
"name" => "TestProject",
"organisation_id" => 555,
"slug" => "test_project",
"identifier" => "tw5555555555555",
"type" => "event",
"transaction_type" => NULL,
"project_target" => 1000,
"image_directory" => NULL,
"allow_more" => FALSE,
"last_update" => 1614166801,
"embed" => [
"page" => "https://spenden.twingle.de/my-awesome-ngo/testprojekt/tw555555a555555c/page",
"eventpage" => "https://my-awesome-ngo/event/testprojekt/tw555555a555555c/edit",
"widget" => "<!-- twingle --><!-- twingle -->",
"form" => "<!-- twingle --><!-- twingle -->",
"widget-single" => "<!-- twingle --><!-- twingle -->",
"form-single" => "<!-- twingle --><!-- twingle -->",
"eventall" => "<!-- twingle --><!-- twingle -->",
"eventlist" => "<!-- twingle --><!-- twingle -->",
"eventeditcreate" => "<!-- twingle --><!-- twingle -->",
"giftdonationexample" => "https://spenden.twingle.de/gift/my-awesome-ngo/tw555555a555555c/example",
"letterexample" => "https://spenden.twingle.de/letter/my-awesome-ngo/tw555555a555555c/example",
],
"counter-url" => [
"url" => "https://donationstatus.twingle.de/donation-status/555aaa",
],
"host" => "https://spenden.twingle.de/",
"project_options" => [
"id" => 2237,
"has_confirmation_mail" => FALSE,
"has_confirmation_mail_api" => FALSE,
"has_donation_receipt" => TRUE,
"has_contact_data" => FALSE,
"donation_rhythm" => [
"yearly" => TRUE,
"halfyearly" => FALSE,
"quarterly" => TRUE,
"monthly" => TRUE,
"one_time" => TRUE,
],
"default_rhythm" => "",
"has_newsletter_registration" => FALSE,
"has_postinfo_registration" => FALSE,
"design_background_color" => "not_a_hex", // not a hex
"design_primary_color" => "green", // no hex either
"design_font" => "",
"design_font_color" => "true", // no hex either
"design_button_font_color" => "",
"design_button_font_color_light" => "",
"image" => "",
"bcc_email_address" => "mustermann@awesome", // no valid email
"donation_value_min" => 50, // higher than max
"donation_value_max" => 10,
"donation_value_default" => 30, // higher than max, lower than min
"exclude_contact_fields" => "company,birthday,telephone",
"mandatory_contact_fields" => "firstname,lastname",
"custom_js" => NULL,
"custom_css" => "",
"share_url" => "not_a_url", // no valid url
"has_contact_mandatory" => FALSE,
"has_doi" => TRUE,
"doi_redirect" => NULL,
"has_force_donation_target_buttons" => FALSE,
"has_show_single_target" => FALSE,
"betterpayment_credit_card_theme" => NULL,
"app_js" => NULL,
"slidericon" => "handshake",
"extra_field" => [],
"has_hidden_logo" => FALSE,
"has_projecttarget_as_money" => FALSE,
"rapidmail_recipient_list" => NULL,
"mailchimp_recipient_list" => NULL,
"has_mailchimp_add_all_user" => NULL,
"has_mail_hide_paymentblock" => FALSE,
"has_mail_hide_paymentblock_api" => FALSE,
"cleverreach_group_id" => NULL,
"cleverreach_form_id" => NULL,
"has_donationtarget_textfield" => FALSE,
"has_civi_crm_activated" => FALSE,
"has_step_index" => FALSE,
"gift_donation" => "",
"gift_donation_icon" => NULL,
"gift_donation_image" => NULL,
"languages" => "de",
"has_buttons" => FALSE,
"has_no_slider" => FALSE,
"buttons" => [
"button1" => [
"amount" => "5",
],
"button2" => [
"amount" => "50",
],
"button3" => [
"amount" => "100",
],
"button4" => [
"amount" => "",
],
],
"has_newsletter_namerequest" => FALSE,
"has_show_donator_data" => FALSE,
"has_donation_letter" => FALSE,
"has_donation_letter_api" => FALSE,
"amount_images" => [],
"video_url" => NULL,
],
"payment_methods" => [
"has_paypal" => TRUE,
"has_betterpayment" => FALSE,
"has_sixpay" => FALSE,
"has_banktransfer" => TRUE,
"has_debit" => TRUE,
"has_sofortueberweisung" => FALSE,
"has_betterpayment_creditcard" => FALSE,
"has_mbe4" => FALSE,
"has_generic" => FALSE,
"has_konfipay" => FALSE,
"has_konfipay_recurring" => FALSE,
"has_betterpayment_creditcard_recurring" => FALSE,
"has_paypal_recurring" => FALSE,
"has_debit_recurring" => TRUE,
"has_generic_recurring" => FALSE,
"has_sixpay_recurring" => FALSE,
"has_apple_pay" => FALSE,
"has_apple_pay_recurring" => FALSE,
"has_paydirekt" => FALSE,
"has_paydirekt_recurring" => FALSE,
],
];

View file

@ -0,0 +1,137 @@
<?php
return [
"id" => 2243,
"internal_id" => NULL,
"name" => "TestProject",
"organisation_id" => 555,
"slug" => "test_project",
"identifier" => "tw5555555555555",
"type" => "event",
"transaction_type" => NULL,
"project_target" => 1000,
"image_directory" => NULL,
"allow_more" => FALSE,
"last_update" => 1614166801,
"embed" => [
"page" => "https://spenden.twingle.de/my-awesome-ngo/testprojekt/tw555555a555555c/page",
"eventpage" => "https://my-awesome-ngo/event/testprojekt/tw555555a555555c/edit",
"widget" => "<!-- twingle --><!-- twingle -->",
"form" => "<!-- twingle --><!-- twingle -->",
"widget-single" => "<!-- twingle --><!-- twingle -->",
"form-single" => "<!-- twingle --><!-- twingle -->",
"eventall" => "<!-- twingle --><!-- twingle -->",
"eventlist" => "<!-- twingle --><!-- twingle -->",
"eventeditcreate" => "<!-- twingle --><!-- twingle -->",
"giftdonationexample" => "https://spenden.twingle.de/gift/my-awesome-ngo/tw555555a555555c/example",
"letterexample" => "https://spenden.twingle.de/letter/my-awesome-ngo/tw555555a555555c/example",
],
"counter-url" => [
"url" => "https://donationstatus.twingle.de/donation-status/555aaa",
],
"host" => "https://spenden.twingle.de/",
"project_options" => [
"id" => 2237,
"has_confirmation_mail" => FALSE,
"has_confirmation_mail_api" => FALSE,
"has_donation_receipt" => TRUE,
"has_contact_data" => FALSE,
"donation_rhythm" => [
"yearly" => TRUE,
"halfyearly" => FALSE,
"quarterly" => TRUE,
"monthly" => TRUE,
"one_time" => TRUE,
],
"default_rhythm" => "",
"has_newsletter_registration" => FALSE,
"has_postinfo_registration" => FALSE,
"design_background_color" => "ffffff",
"design_primary_color" => "102045",
"design_font" => "",
"design_font_color" => "102045",
"design_button_font_color" => "",
"design_button_font_color_light" => "",
"image" => "",
"bcc_email_address" => "mustermann@awesome-ngo.org",
"donation_value_min" => 5,
"donation_value_max" => 1000,
"donation_value_default" => 50,
"exclude_contact_fields" => "company,birthday,telephone",
"mandatory_contact_fields" => "firstname,lastname",
"custom_js" => NULL,
"custom_css" => "https://awesome-ngo.org/css",
"share_url" => "https://awesome-ngo.org/donate",
"has_contact_mandatory" => FALSE,
"has_doi" => TRUE,
"doi_redirect" => NULL,
"has_force_donation_target_buttons" => FALSE,
"has_show_single_target" => FALSE,
"betterpayment_credit_card_theme" => NULL,
"app_js" => NULL,
"slidericon" => "handshake",
"extra_field" => [
],
"has_hidden_logo" => FALSE,
"has_projecttarget_as_money" => FALSE,
"rapidmail_recipient_list" => NULL,
"mailchimp_recipient_list" => NULL,
"has_mailchimp_add_all_user" => NULL,
"has_mail_hide_paymentblock" => FALSE,
"has_mail_hide_paymentblock_api" => FALSE,
"cleverreach_group_id" => NULL,
"cleverreach_form_id" => NULL,
"has_donationtarget_textfield" => FALSE,
"has_civi_crm_activated" => FALSE,
"has_step_index" => FALSE,
"gift_donation" => "",
"gift_donation_icon" => NULL,
"gift_donation_image" => NULL,
"languages" => "de",
"has_buttons" => FALSE,
"has_no_slider" => FALSE,
"buttons" => [
"button1" => [
"amount" => "5",
],
"button2" => [
"amount" => "50",
],
"button3" => [
"amount" => "100",
],
"button4" => [
"amount" => "",
],
],
"has_newsletter_namerequest" => FALSE,
"has_show_donator_data" => FALSE,
"has_donation_letter" => FALSE,
"has_donation_letter_api" => FALSE,
"amount_images" => [],
"video_url" => NULL,
],
"payment_methods" => [
"has_paypal" => TRUE,
"has_betterpayment" => FALSE,
"has_sixpay" => FALSE,
"has_banktransfer" => TRUE,
"has_debit" => TRUE,
"has_sofortueberweisung" => FALSE,
"has_betterpayment_creditcard" => FALSE,
"has_mbe4" => FALSE,
"has_generic" => FALSE,
"has_konfipay" => FALSE,
"has_konfipay_recurring" => FALSE,
"has_betterpayment_creditcard_recurring" => FALSE,
"has_paypal_recurring" => FALSE,
"has_debit_recurring" => TRUE,
"has_generic_recurring" => FALSE,
"has_sixpay_recurring" => FALSE,
"has_apple_pay" => FALSE,
"has_apple_pay_recurring" => FALSE,
"has_paydirekt" => FALSE,
"has_paydirekt_recurring" => FALSE,
],
];

View file

@ -1,6 +1,8 @@
<?php
use CRM_TwingleCampaign_Utils_ExtensionCache as ExtensionCache;
use CRM_TwingleCampaign_BAO_TwingleProject as TwingleProject;
use CRM_TwingleCampaign_BAO_TwingleApiCall as TwingleApiCall;
use CRM_TwingleCampaign_ExtensionUtil as E;
require_once 'twinglecampaign.civix.php';
@ -9,6 +11,7 @@ require_once 'twinglecampaign.civix.php';
* Implements hook_civicrm_config().
*
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config/
*
* @param $config
*/
function twinglecampaign_civicrm_config(&$config) {
@ -63,15 +66,20 @@ function twinglecampaign_civicrm_postSave_civicrm_campaign($dao) {
// If the db transaction is still running, add a function to it that will
// be called afterwards
if (CRM_Core_Transaction::isActive()) {
CRM_Core_Transaction::addCallback(
CRM_Core_Transaction::PHASE_POST_COMMIT,
'twinglecampaign_postSave_campaign_callback',
[$dao->id, $dao->campaign_type_id]
);
if (_validateAndSendInput($dao->id, $dao->campaign_type_id)) {
CRM_Core_Transaction::addCallback(
CRM_Core_Transaction::PHASE_POST_COMMIT,
'twinglecampaign_postSave_campaign_update_callback',
[$dao->id, $dao->campaign_type_id]
);
}
}
// If the transaction is already finished, call the function directly
else {
twinglecampaign_postSave_campaign_callback($dao->id, $dao->campaign_type_id);
twinglecampaign_postSave_campaign_update_callback($dao->id, $dao->campaign_type_id);
}
}
@ -89,21 +97,13 @@ function twinglecampaign_civicrm_postSave_civicrm_campaign($dao) {
*
* @throws \CiviCRM_API3_Exception
*/
function twinglecampaign_postSave_campaign_callback (
function twinglecampaign_postSave_campaign_update_callback(
int $campaign_id,
int $campaign_type_id
) {
// Get campaign type id for TwingleProject
$twingle_project_campaign_type_id =
ExtensionCache::getInstance()
->getCampaigns()['campaign_types']['twingle_project']['id'];
// Get campaign type id for TwingleCampaign
$twingle_campaign_campaign_type_id =
ExtensionCache::getInstance()
->getCampaigns()['campaign_types']['twingle_campaign']['id'];
$twingle_project_campaign_type_id = _get_campaign_type_id_twingle_project();
$twingle_campaign_campaign_type_id = _get_campaign_type_id_twingle_campaign();
// If $campaign_type_id is a TwingleProject or TwingleCampaign campaign,
// synchronize it
@ -121,15 +121,14 @@ function twinglecampaign_postSave_campaign_callback (
}
if (isset($_POST['action'])) {
if ($_POST['action'] == 'clone') {
if ($_POST['action'] == 'clone' && $entity == 'TwingleProject') {
unset($_POST['action']);
$result = civicrm_api3($entity, 'getsingle',
$result = civicrm_api3('TwingleProject', 'getsingle',
['id' => $campaign_id]
)['values'][$campaign_id];
$className = 'CRM_TwingleCampaign_BAO_' . $entity;
);
$id = $result['id'];
unset($result['id']);
$project = new $className($result, $id);
$project = new TwingleProject($result, $id);
try {
$project->clone();
} catch (Exception $e) {
@ -137,51 +136,42 @@ function twinglecampaign_postSave_campaign_callback (
E::LONG_NAME .
' could not clone ' . $entity . ': ' . $e->getMessage()
);
CRM_Utils_System::setUFMessage($entity . ' could not get cloned.');
}
}
elseif ($entity == 'TwingleProject') {
try {
civicrm_api3('TwingleProject', 'sync', ['id' => $campaign_id]);
CRM_Utils_System::setUFMessage('TwingleProject was saved.');
} catch (CiviCRM_API3_Exception $e) {
Civi::log()->error(
'twinglecampaign_postSave_callback ' . $e->getMessage()
);
}
}
else {
try {
civicrm_api3('TwingleCampaign', 'create', ['id' => $campaign_id]);
CRM_Utils_System::setUFMessage('TwingleCampaign was saved.');
} catch (CiviCRM_API3_Exception $e) {
Civi::log()->error(
'twinglecampaign_postSave_callback ' . $e->getMessage()
CRM_Core_Session::setStatus(
$e->getMessage(),
E::ts("Campaign cloning failed"),
error,
[unique => TRUE]
);
}
}
}
// If a TwingleProject is getting saved
elseif ($entity == 'TwingleProject') {
// Also synchronize all child TwingleCampaign campaigns
// Synchronize all child TwingleCampaign campaigns
try {
civicrm_api3('TwingleCampaign', 'sync', ['project_id' => $campaign_id]);
civicrm_api3(
'TwingleCampaign',
'sync',
['parent_id' => $campaign_id]);
} catch (CiviCRM_API3_Exception $e) {
CRM_Core_Session::setStatus(
$e->getMessage(),
E::ts("TwingleCampaign update failed"),
error, [unique => TRUE]
);
Civi::log()->error(
'twinglecampaign_postSave_callback ' . $e->getMessage()
E::SHORT_NAME .
' Update of TwingleCampaigns failed: ' . $e->getMessage()
);
}
}
else {
try {
civicrm_api3('TwingleProject', 'sync', ['id' => $campaign_id]);
CRM_Utils_System::setUFMessage('TwingleProject was saved.');
} catch (CiviCRM_API3_Exception $e) {
Civi::log()->error(
'twinglecampaign_postSave_callback ' . $e->getMessage()
);
}
} else {
try {
civicrm_api3('TwingleCampaign', 'create', ['id' => $campaign_id]);
CRM_Utils_System::setUFMessage('TwingleCampaign was saved.');
civicrm_api3('TwingleCampaign', 'create',
['id' => $campaign_id, 'parent_id' => $_POST['parent_id']]);
CRM_Utils_System::setUFMessage(E::ts('TwingleCampaign was saved.'));
} catch (CiviCRM_API3_Exception $e) {
Civi::log()->error(
'twinglecampaign_postSave_callback ' . $e->getMessage()
@ -191,6 +181,189 @@ function twinglecampaign_postSave_campaign_callback (
}
}
function _get_campaign_type_id_twingle_project() {
return ExtensionCache::getInstance()
->getCampaignIds()['campaign_types']['twingle_project']['id'];
}
function _get_campaign_type_id_twingle_campaign() {
return ExtensionCache::getInstance()
->getCampaignIds()['campaign_types']['twingle_campaign']['id'];
}
/**
* Callback to sync a project after its creation.
* @param int $campaign_id
*/
function twinglecampaign_postSave_project_create_callback(
int $campaign_id
) {
try {
civicrm_api3(
'TwingleProject',
'sync',
['id' => $campaign_id]);
} catch (Exception $e) {
CRM_Core_Session::setStatus(
$e->getMessage(),
E::ts("TwingleProject creation failed"),
error, [unique => TRUE]
);
Civi::log()->error(
E::SHORT_NAME .
' Update of TwingleProject creation failed: ' . $e->getMessage()
);
}
}
/**
* First validate and then sends the input of this transaction to Twinge.
* If the call to the Twingle API succeeded, this function returns TRUE;
*
* @param $id
* @param $campaign_type_id
*
* @return bool
* @throws \CiviCRM_API3_Exception
*/
function _validateAndSendInput($id, $campaign_type_id): bool {
// Set callback for cloning
if (isset($_POST['action'])) {
CRM_Core_Transaction::addCallback(
CRM_Core_Transaction::PHASE_POST_COMMIT,
'twinglecampaign_postSave_campaign_update_callback',
[$id, $campaign_type_id]
);
return FALSE;
}
if ($campaign_type_id == _get_campaign_type_id_twingle_project()) {
// Instantiate project
$project = new TwingleProject();
// Translate custom fields from $_POST
$customFields = [];
$customFieldsKeys = preg_grep('/^custom_/', array_keys($_POST));
foreach ($customFieldsKeys as $key) {
$customFields[preg_replace('/_-?\d*$/', '', $key)] =
$_POST[$key];
}
$project->translateCustomFields(
$customFields,
TwingleProject::OUT
);
TwingleProject::formatValues($customFields, TwingleProject::OUT);
// Update project
$project->update($customFields);
// Validate project values
$validation = $project->validate();
// If the input is valid, send it to Twingle
if ($validation['valid']) {
// Try to retrieve twingleApi from cache or create a new
$twingleApi = Civi::cache()->get('twinglecampaign_twingle_api');
if (NULL === $twingleApi) {
try {
$twingleApi =
new TwingleApiCall(Civi::settings()->get('twingle_api_key'));
} catch (Exception $e) {
// Roll back transaction if input validation failed
CRM_Core_Transaction::rollbackIfFalse(FALSE);
CRM_Core_Session::setStatus(
$e->getMessage(),
E::ts("Could not retrieve Twingle API key"),
error,
[unique => TRUE]
);
Civi::log()->error(
E::SHORT_NAME .
' Could not retrieve Twingle API key: ' . $e->getMessage()
);
}
Civi::cache('long')->set('twinglecampaign_twingle_api', $twingleApi);
}
try {
// Complement project values with values from Twingle if it has a
// project_id
if ($project->getProjectId()) {
$project_from_twingle = $twingleApi->getProject($project->getProjectId());
$project->complement($project_from_twingle);
}
// If this campaign is just about to become created, add a callback to
// sync it after the transaction has finished
else {
CRM_Core_Transaction::addCallback(
CRM_Core_Transaction::PHASE_POST_COMMIT,
'twinglecampaign_postSave_project_create_callback', [$id]
);
return FALSE;
}
// Push project
require E::path() . '/api/v3/TwingleProject/Sync.php';
$result = _pushProjectToTwingle($project, $twingleApi, [], FALSE);
if ($result['is_error'] != 0) {
throw new \CiviCRM_API3_Exception($result['error_message']);
}
} catch (Exception $e) {
// Roll back transaction if input validation failed
CRM_Core_Transaction::rollbackIfFalse(FALSE);
// Display and log error message
CRM_Core_Session::setStatus(
$e->getMessage(),
E::ts("TwingleProject synchronization failed: %1",
[1 => $e->getMessage()]),
error,
[unique => TRUE]
);
Civi::log()->error(
E::SHORT_NAME .
' TwingleProject synchronization failed: ' . $e->getMessage()
);
// Push failed
return FALSE;
}
// Push succeeded
return TRUE;
}
// Display error message if validation failed
else {
// Roll back transaction if input validation failed
CRM_Core_Transaction::rollbackIfFalse(FALSE);
// Build error message
$errorMessage = '<ul>';
foreach ($validation['messages'] as $message) {
$errorMessage = $errorMessage . '<li>' . $message . '</li>';
}
$errorMessage = $errorMessage . '</ul>';
CRM_Core_Session::setStatus(
$errorMessage,
E::ts("Input validation failed"),
error,
[unique => TRUE]
);
// Validation failed
return FALSE;
}
}
// TwingleCampaigns always return TRUE;
return TRUE;
}
///**
// * ## Implements hook_civicrm_post().