remove project options & add embed data

This commit is contained in:
Marc Michalsky forumZFD 2020-10-29 16:26:00 +01:00
parent 52a3a1e978
commit 6e07d97dba
Signed by untrusted user who does not match committer: marc.koch
GPG key ID: 12406554CFB028B9
5 changed files with 78 additions and 1430 deletions

View file

@ -42,8 +42,6 @@ class TwingleProject {
private $values; private $values;
private $options;
/** /**
* TwingleProject constructor. * TwingleProject constructor.
@ -63,12 +61,6 @@ class TwingleProject {
// Fetch custom field mapping once // Fetch custom field mapping once
self::init(); self::init();
// Create TwingleProjectOptions object
$this->options = new TwingleProjectOptions($project['options'], $origin);
// Unset project options in $project array
unset($project['options']);
// If values come from CiviCRM Campaign API // If values come from CiviCRM Campaign API
if ($origin == self::CIVICRM) { if ($origin == self::CIVICRM) {
@ -172,28 +164,11 @@ class TwingleProject {
self::IN self::IN
); );
// Prepare project option values for import into database
$options_prepared_for_import = $this->options->getValues();
TwingleProjectOptions::formatValues(
$options_prepared_for_import,
self::IN
);
self::translateCustomFields(
$options_prepared_for_import,
self::IN
);
// Merge project values and project options values
$merged = array_merge(
$values_prepared_for_import,
$options_prepared_for_import
);
// Set id // Set id
$merged['id'] = $this->id; $values_prepared_for_import['id'] = $this->id;
// Create campaign // Create campaign
$result = civicrm_api3('Campaign', 'create', $merged); $result = civicrm_api3('Campaign', 'create', $values_prepared_for_import);
// Update id // Update id
$this->id = $result['id']; $this->id = $result['id'];
@ -226,12 +201,6 @@ class TwingleProject {
*/ */
public function update(array $values) { public function update(array $values) {
// Update project options
$this->options->update($values['options']);
// Unset options array in project values
unset($values['options']);
// Update project values // Update project values
$this->values = array_merge($this->values, $values); $this->values = array_merge($this->values, $values);
} }
@ -250,7 +219,6 @@ class TwingleProject {
$values = $this->values; $values = $this->values;
self::formatValues($values, self::OUT); self::formatValues($values, self::OUT);
self::translateKeys($values, self::OUT);
// Get template for project // Get template for project
$project = self::$templates['project']; $project = self::$templates['project'];
@ -265,37 +233,6 @@ class TwingleProject {
return $values; return $values;
} }
/**
* Export options. Ensures that only those values will be exported which the
* Twingle API expects. Missing values will get complemented with default
* values.
*
* @return array
* Array with all options to send to the Twingle API
*
* @throws Exception
*
*/
public function exportOptions() {
$options = $this->values['options'];
self::formatValues($options, self::OUT);
self::translateKeys($options, self::OUT);
// Get Template for project options
$project_options_template = self::$templates['project_options'];
// Replace array items which the Twingle API does not expect
foreach ($options as $key => $value) {
if (!key_exists($key, $project_options_template)) {
unset($options[$key]);
}
}
// Complement missing options with default values
return array_merge($project_options_template, $options);
}
/** /**
* Check if a TwingleProject campaign already exists and if so set attributes * Check if a TwingleProject campaign already exists and if so set attributes
@ -349,9 +286,6 @@ class TwingleProject {
// Translate keys from CiviCRM format to Twingle format // Translate keys from CiviCRM format to Twingle format
self::translateKeys($values, self::OUT); self::translateKeys($values, self::OUT);
// Separate options from project values
self::separateOptions($values);
// Set attributes to the values of the existing TwingleProject campaign // Set attributes to the values of the existing TwingleProject campaign
// to reflect the state of the actual campaign in the database // to reflect the state of the actual campaign in the database
$this->update($values); $this->update($values);
@ -379,9 +313,6 @@ class TwingleProject {
'id' => $id, 'id' => $id,
]); ]);
// Separate options from project values
self::separateOptions($result['values']);
return new TwingleProject( return new TwingleProject(
$result['values'], $result['values'],
self::CIVICRM self::CIVICRM
@ -484,14 +415,17 @@ class TwingleProject {
elseif ($direction == self::OUT) { elseif ($direction == self::OUT) {
// Change DateTime string into timestamp // Change DateTime string into timestamp
$values['last_modified_date'] = $values['last_update'] =
self::getTimestamp($values['last_modified_date']); self::getTimestamp($values['last_update']);
// default project_type to '' // Default project_type to ''
$values['type'] = $values['type'] == 'default' $values['type'] = $values['type'] == 'default'
? '' ? ''
: $values['type']; : $values['type'];
// Cast project target to integer
$values['project_target'] = (int) $values['project_target'];
} }
else { else {
@ -568,30 +502,31 @@ class TwingleProject {
} }
/** /**
* A function that picks all option values from the values array and puts them * Set embed data fields
* into an own array.
* *
* @param array $values * @param array $embedData
* Array with embed data from Twingle API
*/ */
private static function separateOptions(array &$values) { public function setEmbedData(array $embedData) {
$options = []; // Get all embed_data keys from template
$embed_data_keys = self::$templates['project_embed_data'];
// Get array with template for project values and options // Transfer all embed_data values
$options_template = self::$templates['project_options']; foreach ($embed_data_keys as $key) {
$this->values[$key] = htmlspecialchars($embedData[$key]);
// Map array items into $values and $options array
foreach ($values as $key => $value) {
if (key_exists($key, $options_template)) {
$options[$key] = $value;
unset($values[$key]);
}
} }
// Insert options array into values array
$values['options'] = $options;
} }
/**
* Set counter url
*
* @param String $counterUrl
* URL of the counter
*/
public function setCounterUrl(string $counterUrl) {
$this->values['counter'] = $counterUrl;
}
/** /**
* Deactivate this TwingleProject campaign * Deactivate this TwingleProject campaign
@ -654,10 +589,11 @@ class TwingleProject {
*/ */
public function getResponse(string $status) { public function getResponse(string $status) {
return [ return [
'title' => $this->values['name'], 'title' => $this->values['name'],
'id' => (int) $this->id, 'id' => (int) $this->id,
'project_id' => (int) $this->values['id'], 'project_id' => (int) $this->values['id'],
'status' => $status, 'project_type' => $this->values['type'],
'status' => $status,
]; ];
} }
@ -730,12 +666,8 @@ class TwingleProject {
* @return int|null * @return int|null
*/ */
public function lastUpdate() { public function lastUpdate() {
$lastProjectUpdate = self::getTimestamp($this->values['last_update']);
$lastOptionsUpdate = self::getTimestamp($this->options->lastUpdate()); return self::getTimestamp($this->values['last_update']);
$lastUpdate = $lastProjectUpdate > $lastOptionsUpdate
? $lastProjectUpdate
: $lastOptionsUpdate;
return self::getTimestamp($lastUpdate);
} }

View file

@ -1,243 +0,0 @@
<?php
namespace CRM\TwingleCampaign\BAO;
use CRM_TwingleCampaign_ExtensionUtil as E;
use CRM_Utils_Array;
use Exception;
include_once E::path() . '/CRM/TwingleCampaign/BAO/CustomField.php';
class TwingleProjectOptions {
private $values;
/**
* TwingleProjectOptions constructor.
*
* @param array $options
* Result array of Twingle API call to
* https://project.twingle.de/api/by-organisation/$project_id/options
*
* @param string $origin
* Origin of the arrays. It can be one of two constants:
* TwingleProject::TWINGLE|CIVICRM
*
* @throws Exception
*/
public function __construct(array $options, string $origin) {
// If values come from CiviCRM Campaign API
if ($origin == TwingleProject::CIVICRM) {
// Translate custom field names into Twingle field names
TwingleProject::translateCustomFields($options, TwingleProject::OUT);
// Format values
self::formatValues($options, TwingleProject::OUT);
}
// Unset project options id
unset($options['id']);
// Set project values attribute
$this->values = $options;
}
/**
* Update an this object
*
* @param array $options
* Array with values to update
*
* @throws Exception
*/
public function update(array $options) {
// Update values
$this->values = array_merge($this->values, $options);
}
/**
* Export values. Ensures that only those values will be exported which the
* Twingle API expects.
*
* @return array
* Array with all values to send to the Twingle API
*
* @throws Exception
*/
public function export() {
$values = $this->values;
self::formatValues($values, TwingleProject::OUT);
TwingleProject::translateKeys($values, TwingleProject::OUT);
// Get Template for project options
$project_options_template = TwingleProject::$templates['project_options'];
// Replace array items which the Twingle API does not expect
foreach ($values as $key => $value) {
if (!key_exists($key, $project_options_template)) {
unset($values[$key]);
}
}
// Format project target format
if (key_exists('has_projecttarget_as_money', $values)) {
$values['has_projecttarget_as_money'] =
$values['has_projecttarget_as_money'] ? 'in Euro' : 'percentage';
}
return $values;
}
/**
* Translate values between CiviCRM Campaigns and Twingle
*
* @param array $values
* array of which values shall be translated
*
* @param string $direction
* TwingleProject::IN -> translate array values from Twingle to CiviCRM <br>
* TwingleProject::OUT -> translate array values from CiviCRM to Twingle
*
* @throws Exception
*/
public static function formatValues(array &$values, string $direction) {
if ($direction == TwingleProject::IN) {
// Change timestamp into DateTime string
if ($values['last_update']) {
$values['last_update'] =
TwingleProject::getDateTime($values['last_update']);
}
// format donation rhythm
if (is_array($values['donation_rhythm'])) {
$tmp = [];
foreach ($values['donation_rhythm'] as $key => $value) {
if ($value) {
$tmp[$key] = $key;
}
}
$values['donation_rhythm'] = CRM_Utils_Array::implodePadded($tmp);
}
// Format contact fields
if ($values['exclude_contact_fields']) {
$possible_contact_fields =
TwingleProject::$campaigns['custom_fields']
['twingle_project_exclude_contact_fields']['option_values'];
$exclude_contact_fields = explode(
',',
$values['exclude_contact_fields']
);
foreach ($exclude_contact_fields as $exclude_contact_field) {
unset($possible_contact_fields[$exclude_contact_field]);
}
$values['exclude_contact_fields'] =
CRM_Utils_Array::implodePadded($possible_contact_fields);
}
// Format languages
if ($values['languages']) {
$values['languages'] =
CRM_Utils_Array::implodePadded(
explode(
',',
$values['languages']
)
);
}
// Format project target format
if (key_exists('has_projecttarget_as_money', $values)) {
$values['has_projecttarget_as_money'] =
$values['has_projecttarget_as_money'] ? 'in Euro' : 'percentage';
}
}
elseif ($direction == TwingleProject::OUT) {
// Change DateTime string into timestamp
$values['last_update'] =
TwingleProject::getTimestamp($values['last_update']);
// format donation rhythm
if (is_array($values['donation_rhythm'])) {
$tmp = [];
foreach ($values['donation_rhythm'] as $key => $value) {
if ($value) {
$tmp[$key] = $key;
}
}
$values['donation_rhythm'] = CRM_Utils_Array::implodePadded($tmp);
}
// Format contact fields
if ($values['exclude_contact_fields']) {
$possible_contact_fields =
TwingleProject::$campaigns['custom_fields']
['twingle_project_exclude_contact_fields']['option_values'];
$exclude_contact_fields = explode(
',',
$values['exclude_contact_fields']
);
foreach ($exclude_contact_fields as $exclude_contact_field) {
unset($possible_contact_fields[$exclude_contact_field]);
}
$values['exclude_contact_fields'] =
CRM_Utils_Array::implodePadded($possible_contact_fields);
}
// Format languages
if ($values['languages']) {
$values['languages'] =
CRM_Utils_Array::implodePadded(
explode(
',',
$values['languages']
)
);
}
// Cast project_target to integer
$values['project_target'] = (int) $values['project_target'];
}
else {
throw new Exception(
"Invalid Parameter $direction for formatValues()"
);
}
}
/**
* @return array
*/
public function getValues(): array {
return $this->values;
}
public function lastUpdate() {
return $this->values['last_update'];
}
}

File diff suppressed because it is too large Load diff

View file

@ -10,77 +10,14 @@
"type", "type",
"last_update" "last_update"
], ],
"event": [ "project_embed_data": [
"widget",
"form",
"form-single",
"widget-single",
"eventall",
"eventlist"
], ],
"project_options": { "event": [
"has_confirmation_mail": false, ]
"has_confirmation_mail_api": false,
"has_donation_receipt": true,
"has_contact_data": false,
"donation_rhythm": {
"yearly": true,
"halfyearly": false,
"quarterly": false,
"monthly": true,
"one_time": true
},
"has_newsletter_registration": false,
"has_postinfo_registration": false,
"design_background_color": "",
"design_primary_color": "",
"design_font": "",
"design_font_color": "",
"design_button_font_color": "",
"design_button_font_color_light": "",
"image": "",
"bcc_email_address": "",
"donation_value_min": 5,
"donation_value_max": 500,
"donation_value_default": 50,
"exclude_contact_fields": "birthday",
"custom_js": null,
"custom_css": null,
"share_url": null,
"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": "heart",
"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,
"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": ""
},
"button2": {
"amount": ""
},
"button3": {
"amount": ""
}
},
"has_newsletter_namerequest": false,
"has_show_donator_data": false,
"has_donation_letter": false,
"has_donation_letter_api": false,
"amount_images": []
}
} }

View file

@ -74,18 +74,6 @@ class TwingleApiCall {
return $response; return $response;
} }
public function getProjectOptions(int $projectId) {
$response = [];
foreach ($this->organisationId as $organisationId) {
$url = $this->protocol . 'project' . $this->baseUrl . $projectId .
'/options';
$response = array_merge($this->curlGet($url));
}
return $response;
}
/** /**
* *
* Returns all Events for the given $projectId * Returns all Events for the given $projectId
@ -138,25 +126,6 @@ class TwingleApiCall {
// If $values is an array // If $values is an array
if (is_array($values)) { if (is_array($values)) {
// Get project options
try {
$values['options'] = $this->getProjectOptions($values['id']);
} catch (Exception $e) {
// Log Exception
Civi::log()->error(
"Failed to instantiate TwingleProject: $e->getMessage()"
);
// Return result array with error description
return [
"title" => $values['name'],
"project_id" => (int) $values['id'],
"status" =>
"Failed to get project options from Twingle: $e->getMessage()",
];
}
// Instantiate TwingleProject // Instantiate TwingleProject
try { try {
$project = new TwingleProject( $project = new TwingleProject(
@ -182,8 +151,9 @@ class TwingleApiCall {
// Check if the TwingleProject campaign already exists // Check if the TwingleProject campaign already exists
if (!$project->exists()) { if (!$project->exists()) {
// ... if not, create it // ... if not, get embed data and create project
try { try {
$this->getEmbedData($project);
$result = $project->create($is_test); $result = $project->create($is_test);
} catch (Exception $e) { } catch (Exception $e) {
@ -206,12 +176,10 @@ class TwingleApiCall {
// If Twingle's version of the project is newer than the CiviCRM // If Twingle's version of the project is newer than the CiviCRM
// TwingleProject campaign update the campaign // TwingleProject campaign update the campaign
$lastUpdate = $values['last_update'] > $values['options']['last_update'] if ($values['last_update'] > $project->lastUpdate()) {
? $values['last_update']
: $values['options']['last_update'];
if ($lastUpdate > $project->lastUpdate()) {
try { try {
$project->update($values); $project->update($values);
$this->getEmbedData($project);
$result = $project->create(); $result = $project->create();
$result['status'] = $result['status'] == 'TwingleProject created' $result['status'] = $result['status'] == 'TwingleProject created'
? 'TwingleProject updated' ? 'TwingleProject updated'
@ -229,7 +197,7 @@ class TwingleApiCall {
} }
// If the CiviCRM TwingleProject campaign was changed, update the project // If the CiviCRM TwingleProject campaign was changed, update the project
// on Twingle's side // on Twingle's side
elseif ($lastUpdate < $project->lastUpdate()) { elseif ($values['last_update'] < $project->lastUpdate()) {
// If this is a test do not make database changes // If this is a test do not make database changes
if ($is_test) { if ($is_test) {
$result = $project->getResponse( $result = $project->getResponse(
@ -243,10 +211,8 @@ class TwingleApiCall {
elseif ($result['status'] == 'TwingleProject exists') { elseif ($result['status'] == 'TwingleProject exists') {
$result = $project->getResponse('TwingleProject up to date'); $result = $project->getResponse('TwingleProject up to date');
} }
} }
// Return a response of the synchronization // Return a response of the synchronization
return $result; return $result;
} }
@ -256,6 +222,25 @@ class TwingleApiCall {
} }
/**
* @param \CRM\TwingleCampaign\BAO\TwingleProject $project
*/
private function getEmbedData(TwingleProject &$project) {
// Prepare url for curl
$url = $this->protocol . 'project' . $this->baseUrl . $project->getProjectId();
// Send curl
$result = $this->curlGet($url);
// Set embed data
$project->setEmbedData($result['embed']);
// Set counter-url
$project->setCounterUrl($result['counter-url']['url']);
}
/** /**
* Sends an curl post call to Twingle to update an existing project and then * Sends an curl post call to Twingle to update an existing project and then
* updates the TwingleProject campaign. * updates the TwingleProject campaign.
@ -267,7 +252,7 @@ class TwingleApiCall {
* Returns a response array that contains title, id, project_id and status * Returns a response array that contains title, id, project_id and status
* *
*/ */
public function updateProject(TwingleProject &$project) { private function updateProject(TwingleProject &$project) {
try { try {
$values = $project->export(); $values = $project->export();
@ -292,7 +277,8 @@ class TwingleApiCall {
if (is_array($result) && !array_key_exists('message', $result)) { if (is_array($result) && !array_key_exists('message', $result)) {
// Try to update the local TwingleProject campaign // Try to update the local TwingleProject campaign
try { try {
$project->update($result, TwingleProject::TWINGLE); $project->update($result);
$this->getEmbedData($project);
$project->create(); $project->create();
return $project->getResponse('TwingleProject pushed to Twingle'); return $project->getResponse('TwingleProject pushed to Twingle');
} catch (Exception $e) { } catch (Exception $e) {