️ implement synchronisation of TwingleProject settings

This commit is contained in:
Marc Michalsky forumZFD 2021-04-12 10:11:06 +02:00
parent 0b1128fce5
commit 4dc3644bb3
Signed by untrusted user who does not match committer: marc.koch
GPG key ID: 12406554CFB028B9
3 changed files with 149 additions and 67 deletions

View file

@ -104,12 +104,11 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
return TRUE; return TRUE;
} }
/** /**
* ## Update instance values * ## Update instance values
* This method updates the **$values** array of this instance with the values * This method updates the **$values** array of this instance with the values
* from the provided array if they are defined in * 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 * @param array $values
* Array with values to update * Array with values to update
@ -118,47 +117,33 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
// Update campaign values // Update campaign values
$filter = Cache::getInstance()->getTemplates()[$this->className]; $filter = Cache::getInstance()->getTemplates()[$this->className];
foreach ($values as $key => $value) { foreach ($values as $key => $value) {
if ($this->className == "TwingleProject" && $key == 'project_id') { if ($this->in_array_r($key, $filter)) {
$this->values['id'] = $value;
}
elseif (in_array($key, $filter)) {
$this->values[$key] = $value; $this->values[$key] = $value;
} }
elseif ($key == 'embed') {
self::setEmbedData($value);
}
elseif ($key == 'counter-url') {
self::setCounterUrl($value['url']);
}
} }
} }
/** /**
* ## Set embed data fields * ## Complement campaign values
* This method sets all embed data fields that are defined in * Complement existing campaign values with new ones
* *CRM/TwingleCampaign/resources/twingle_api_templates.json* * @param array $arrayToComplement
*
* @param array $embedData
* Array with embed data from Twingle API
*/ */
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 private function complement_r($orig, &$fill) {
$embed_data_keys = Cache::getInstance() foreach ($orig as $key => $value) {
->getTemplates()['project_embed_data']; if (is_array($value)) {
$this->complement_r($orig[$key], $fill[$key]);
// Transfer all embed_data values } else {
foreach ($embed_data_keys as $key) { $fill[$key] = $value;
if (array_key_exists($key, $embedData)) {
$this->values[$key] = $embedData[$key];
} }
} }
} }
public static abstract function formatValues(array &$values, string $direction);
public abstract function formatValues(array &$values, string $direction);
/** /**
* ## Translate array keys between CiviCRM Campaigns and Twingle * ## Translate array keys between CiviCRM Campaigns and Twingle

View file

@ -1,6 +1,5 @@
<?php <?php
use CRM_TwingleCampaign_BAO_TwingleProject as TwingleProject;
use CRM_TwingleCampaign_ExtensionUtil as E; use CRM_TwingleCampaign_ExtensionUtil as E;
@ -79,11 +78,41 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
*/ */
public function getProject(int $projectId = NULL): ?array { public function getProject(int $projectId = NULL): ?array {
$url = empty($projectId) // If no project id is provided, return all projects
? $this->protocol . 'project' . $this->baseUrl . 'by-organisation/' . $this->organisationId if (empty($projectId)) {
: $this->protocol . 'project' . $this->baseUrl . $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,67 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
* *
* Returns an array with all project values. * Returns an array with all project values.
* *
* @param TwingleProject $project * @param array $project
* The TwingleProject object that should get pushed to Twingle * The project values array that should get pushed to Twingle
* *
* @return array * @return array
* @throws \Exception * @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 $projectOptions = $project['project_options'];
$values = $project->export(); unset($project['project_options']);
$paymentMethods = $project['payment_methods'];
unset($project['payment_methods']);
// Prepare url for curl try {
if ($values['id']) { if (!isset($project['id'])) {
$url = $this->protocol . 'project' . $this->baseUrl . $values['id']; $url = $this->protocol . 'project' . $this->baseUrl . 'by-organisation/' .
} $this->organisationId;
else {
$url = $this->protocol . 'project' . $this->baseUrl . 'by-organisation/' . // Post project values
$this->organisationId; $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
$updatedProject['project_options'] =
$this->curlPost($url . '/options', $projectOptions);
// Post payment_methods
$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()
);
} }
// Send curl and return result
return $this->curlPost($url, $values);
} }
/** /**
* ## Get event from Twingle * ## Get event from Twingle
* Returns all events for the provided **$projectId** or a single event if an * Returns all events for the provided **$projectId** or a single event if an
@ -197,6 +263,33 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
} }
} }
/**
* ## 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);
}
/** /**
* ## Delete Project * ## Delete Project

View file

@ -189,11 +189,6 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
$project = new TwingleProject($project_from_twingle); $project = new TwingleProject($project_from_twingle);
try { try {
// Get embed data
$project->setEmbedData(
$twingleApi->getProjectEmbedData($project->getProjectId())
);
// If this is a test, do not make db changes // If this is a test, do not make db changes
if (isset($params['is_test']) && $params['is_test']) { if (isset($params['is_test']) && $params['is_test']) {
$returnValues[$project->getId()] = $returnValues[$project->getId()] =
@ -231,14 +226,18 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
$project = new TwingleProject($project_from_civicrm, $id); $project = new TwingleProject($project_from_civicrm, $id);
// sync project // sync project
$result = _projectSync($project, $project_from_twingle, $twingleApi, $params); $result = _projectSync(
if ($result['is_error'] != 0) { $project,
$errors_occurred++; $project_from_twingle,
$twingleApi,
$params);
if (!$result['is_error'] == 0) {
$errors[$result['id']] = $result['error_message'];
$returnValues[$project->getId()] = $returnValues[$project->getId()] =
$project->getResponse($result['error_message']); $project->getResponse($result['error_message']);
} }
else { else {
$returnValues[$project->getId()] = $result['values']; $returnValues[$result['id']] = $result['values'][$result['id']];
} }
break; break;
} }
@ -284,9 +283,7 @@ function _updateProjectLocally(array $project_from_twingle,
try { try {
$project->update($project_from_twingle); $project->update($project_from_twingle);
$project->setEmbedData(
$twingleApi->getProjectEmbedData($project->getProjectId())
);
// If this is a test, do not make db changes // If this is a test, do not make db changes
if (array_key_exists('is_test', $params) && $params['is_test']) { if (array_key_exists('is_test', $params) && $params['is_test']) {
return civicrm_api3_create_success( return civicrm_api3_create_success(
@ -346,7 +343,7 @@ function _pushProjectToTwingle(TwingleProject $project,
// Push project to Twingle // Push project to Twingle
try { try {
$result = $twingleApi->pushProject($project); $result = $twingleApi->pushProject($project->export());
} catch (Exception $e) { } catch (Exception $e) {
Civi::log()->error( Civi::log()->error(
E::LONG_NAME . E::LONG_NAME .
@ -363,11 +360,7 @@ function _pushProjectToTwingle(TwingleProject $project,
// Update local campaign with data returning from Twingle // Update local campaign with data returning from Twingle
if ($result) { if ($result) {
$project->update($result); $project->update($result);
// Get embed data
try { try {
$project->setEmbedData(
$twingleApi->getProjectEmbedData($project->getProjectId())
);
// Create updated campaign // Create updated campaign
$project->create(TRUE); $project->create(TRUE);
$response = $project->getResponse('TwingleProject pushed to Twingle'); $response = $project->getResponse('TwingleProject pushed to Twingle');
@ -432,6 +425,17 @@ function _projectSync(TwingleProject $project,
// 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 ($project_from_twingle['last_update'] < $project->lastUpdate()) { 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); return _pushProjectToTwingle($project, $twingleApi, $params);
} }