From ba9ab9f3245c0cdc88a49e4d6e770396f6b5f5a0 Mon Sep 17 00:00:00 2001 From: Marc Michalsky forumZFD Date: Sat, 17 Apr 2021 16:58:10 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=EF=B8=8F=20Pull=20all=20campaigns=20w?= =?UTF-8?q?ith=20newly=20created=20custom=20fields=20from=20Twingle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit đŸ‡©đŸ‡Ș update German translation --- CRM/TwingleCampaign/BAO/CustomField.php | 10 +++- CRM/TwingleCampaign/Upgrader.php | 64 +++++++++++++++++++--- api/v3/TwingleEvent/Sync.php | 33 +++++++++-- api/v3/TwingleProject/Sync.php | 51 +++++++++++++---- l10n/de_DE/LC_MESSAGES/twinglecampaign.mo | Bin 20445 -> 21047 bytes l10n/de_DE/LC_MESSAGES/twinglecampaign.po | 56 +++++++++++++++---- l10n/pot/twinglecampaign.pot | 36 ++++++++++-- 7 files changed, 206 insertions(+), 44 deletions(-) diff --git a/CRM/TwingleCampaign/BAO/CustomField.php b/CRM/TwingleCampaign/BAO/CustomField.php index dea24f9..174e715 100644 --- a/CRM/TwingleCampaign/BAO/CustomField.php +++ b/CRM/TwingleCampaign/BAO/CustomField.php @@ -62,10 +62,10 @@ class CRM_TwingleCampaign_BAO_CustomField { * * @param bool $upgrade * If true: Does not show UF message if custom field already exists - * + * @returns array Result of custom field creation api call * @throws \CiviCRM_API3_Exception */ - public function create(bool $upgrade = false) { + public function create(bool $upgrade = FALSE): ?array { // Check if the field already exists $field = civicrm_api3( @@ -95,6 +95,7 @@ class CRM_TwingleCampaign_BAO_CustomField { id: $this->id group: $this->custom_group_id" ); + return $this->result; } // If the field could not get created: log error else { @@ -112,12 +113,17 @@ class CRM_TwingleCampaign_BAO_CustomField { $this->result['error_message']"); CRM_Utils_System::setUFMessage(E::ts("Creation of custom field failed. Find more information in the logs.")); } + return $this->result; } } 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."); + return NULL; + } + else { + return NULL; } } diff --git a/CRM/TwingleCampaign/Upgrader.php b/CRM/TwingleCampaign/Upgrader.php index 6cecff9..3d4d94d 100644 --- a/CRM/TwingleCampaign/Upgrader.php +++ b/CRM/TwingleCampaign/Upgrader.php @@ -13,13 +13,14 @@ use CRM_TwingleCampaign_ExtensionUtil as E; */ 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). - /** + * This update function checks whether all custom fields defined in + * CRM/TwingleCampaign/resources/campaigns.php exist and creates them if not. + * To ensure that all newly created custom fields get filled with data, all + * changed campaigns will get pulled from Twingle. * @throws \CiviCRM_API3_Exception */ - public function upgrade_01() { + public function upgrade_01(): bool { $campaign_info = require E::path() . '/CRM/TwingleCampaign/resources/campaigns.php'; @@ -31,7 +32,7 @@ class CRM_TwingleCampaign_Upgrader extends CRM_TwingleCampaign_Upgrader_Base { new CampaignType($campaign_type); } foreach (CampaignType::getCampaignTypes() as $campaign_type) { - $campaign_type->create(true); + $campaign_type->create(TRUE); } // Create custom groups @@ -42,13 +43,61 @@ class CRM_TwingleCampaign_Upgrader extends CRM_TwingleCampaign_Upgrader_Base { } } $cg = new CustomGroup($custom_group); - $cg->create(true); + $cg->create(TRUE); } + // If new fields get created during the update, set a flag to set all + // last_update values of the affected campaigns to "0" and trigger a + // synchronization. This ensures that settings on Twingle's side will not + // get overwritten with empty values. + $updatedCampaignTypes = []; + // Create custom fields foreach ($campaign_info['custom_fields'] as $custom_field) { $cf = new CustomField($custom_field); - $cf->create(true); + $result = $cf->create(TRUE); + + if (!empty($result)) { + preg_match( + '/^Twingle_[a-yA-Z]*/', + $cf->getCustomGroupId(), + $updatedCampaignTypes[] + ); + } + } + + // Filter changed campaign types + foreach ($updatedCampaignTypes as $key => $value) { + $updatedCampaignTypes[str_replace('_', '', $value[0])] + = TRUE; + unset($updatedCampaignTypes[$key]); + } + + // Pull changed campaigns to fill new created fields with data + try { + foreach ($updatedCampaignTypes as $key => $value) { + if ($value === TRUE) { + civicrm_api3( + $key, + 'sync', + ['pull' => TRUE] + ); + } + } + } catch (Exception $e) { + Civi::log()->error( + E::LONG_NAME . + ' could not pull campaigns from Twingle to fill the campaign fields that were created on update.' . + $e->getMessage() + ); + CRM_Core_Session::setStatus( + E::ts( + 'Could not pull campaigns from Twingle to fill the campaign fields that were created within this update: %1', + [1 => $e->getMessage()] + ), + E::ts('Scheduled Job'), + error + ); } // Create option values @@ -124,7 +173,6 @@ class CRM_TwingleCampaign_Upgrader extends CRM_TwingleCampaign_Upgrader_Base { E::ts('Scheduled Job'), error ); - CRM_Utils_System::setUFMessage(E::ts('Could not create scheduled job "TwingleSync". Your Campaigns will not get synchronized to Twingle.')); } } diff --git a/api/v3/TwingleEvent/Sync.php b/api/v3/TwingleEvent/Sync.php index 9de54cb..23a8b88 100644 --- a/api/v3/TwingleEvent/Sync.php +++ b/api/v3/TwingleEvent/Sync.php @@ -41,6 +41,13 @@ function _civicrm_api3_twingle_event_Sync_spec(array &$spec) { 'api.required' => 0, 'description' => E::ts('If this is set true, no database change will be made'), ]; + $spec['pull'] = [ + 'name' => 'pull', + 'title' => E::ts('Pull'), + 'type' => CRM_Utils_Type::T_BOOLEAN, + 'api.required' => 0, + 'description' => E::ts('If this is set true, the event(s) will be pulled from Twingle and updated locally'), + ]; $spec['twingle_api_key'] = [ 'name' => 'twingle_api_key', 'title' => E::ts('Twingle API key'), @@ -111,6 +118,10 @@ function civicrm_api3_twingle_event_Sync(array $params): array { Civi::cache('long')->set('twinglecampaign_twingle_api', $twingleApi); } + // Set pull flag + $pull = (isset($params['pull']) && $params['pull']); + unset($params['pull']); + // If an id or a event_id is provided, synchronize only this one campaign if (isset($params['id']) || isset($params['event_id'])) { @@ -141,7 +152,13 @@ function civicrm_api3_twingle_event_Sync(array $params): array { } // Synchronize events if (!empty($event_from_twingle)) { - return _eventSync($event, $event_from_twingle, $twingleApi, $params); + return _eventSync( + $event, + $event_from_twingle, + $twingleApi, + $params, + $pull + ); } // If Twingle does not know an event with the given event_id, give error @@ -271,7 +288,13 @@ function civicrm_api3_twingle_event_Sync(array $params): array { $event = _instantiateEvent($event_from_civicrm, $event_from_civicrm['id']); // sync event - $result = _eventSync($event, $event_from_twingle, $twingleApi, $params); + $result = _eventSync( + $event, + $event_from_twingle, + $twingleApi, + $params, + $pull + ); if ($result['is_error'] != 0) { $errors_occurred++; $result_values[$event->getId()] = @@ -394,6 +417,7 @@ function _updateEventLocally(array $event_from_twingle, * @param array $event_from_twingle * @param \CRM_TwingleCampaign_BAO_TwingleApiCall $twingleApi * @param array $params + * @param bool $pull Force pulling event from Twingle and update local campaign * * @return array * @throws \CiviCRM_API3_Exception @@ -401,12 +425,13 @@ function _updateEventLocally(array $event_from_twingle, function _eventSync(TwingleEvent $event, array $event_from_twingle, TwingleApiCall $twingleApi, - array $params): array { + array $params, + bool $pull = FALSE): array { // If Twingle's timestamp of the event differs from the timestamp of the // CiviCRM TwingleEvent campaign, update the campaign on CiviCRM's side. // NOTE: Changes on TwingleEvents are not meant to get pushed to Twingle - if ($event_from_twingle['updated_at'] != $event->lastUpdate()) { + if ($event_from_twingle['updated_at'] != $event->lastUpdate() || $pull) { return _updateEventLocally($event_from_twingle, $event, $params, $twingleApi); } diff --git a/api/v3/TwingleProject/Sync.php b/api/v3/TwingleProject/Sync.php index 7768997..0906f14 100644 --- a/api/v3/TwingleProject/Sync.php +++ b/api/v3/TwingleProject/Sync.php @@ -35,6 +35,13 @@ function _civicrm_api3_twingle_project_Sync_spec(array &$spec) { 'api.required' => 0, 'description' => E::ts('If this is set true, no database change will be made'), ]; + $spec['pull'] = [ + 'name' => 'pull', + 'title' => E::ts('Pull from Twingle'), + 'type' => CRM_Utils_Type::T_BOOLEAN, + 'api.required' => 0, + 'description' => E::ts('If this is set true, the project(s) will be pulled from Twingle and updated locally'), + ]; $spec['twingle_api_key'] = [ 'name' => 'twingle_api_key', 'title' => E::ts('Twingle API key'), @@ -90,6 +97,10 @@ function civicrm_api3_twingle_project_Sync(array $params): array { Civi::cache('long')->set('twinglecampaign_twingle_api', $twingleApi); } + // Set pull flag + $pull = (isset($params['pull']) && $params['pull']); + unset($params['pull']); + // If an id or a project_id is given, synchronize only this one campaign if (isset($params['id']) || isset($params['project_id'])) { @@ -106,9 +117,15 @@ function civicrm_api3_twingle_project_Sync(array $params): array { $id = $result['id']; $project = new TwingleProject($result, $id); - // Synchronize projects + // Synchronize project if (!empty($project_from_twingle)) { - return _projectSync($project, $project_from_twingle, $twingleApi, $params); + return _projectSync( + $project, + $project_from_twingle, + $twingleApi, + $params, + $pull + ); } // If Twingle does not know a project with the given project_id, give error @@ -175,8 +192,10 @@ function civicrm_api3_twingle_project_Sync(array $params): array { // Push missing projects to Twingle $returnValues = []; foreach ($projects_from_civicrm['values'] as $project_from_civicrm) { - if (!in_array($project_from_civicrm['project_id'], - array_column($projects_from_twingle, 'id'))) { + if ( + !in_array($project_from_civicrm['project_id'], + array_column($projects_from_twingle, 'id') + )) { // store campaign id in $id $id = $project_from_civicrm['id']; unset($project_from_civicrm['id']); @@ -197,8 +216,11 @@ function civicrm_api3_twingle_project_Sync(array $params): array { // Create missing projects as campaigns in CiviCRM foreach ($projects_from_twingle as $project_from_twingle) { - if (!in_array($project_from_twingle['id'], - array_column($projects_from_civicrm['values'], 'project_id'))) { + if ( + !in_array($project_from_twingle['id'], + array_column($projects_from_civicrm['values'], + 'project_id') + )) { $project = new TwingleProject($project_from_twingle); try { @@ -241,10 +263,12 @@ function civicrm_api3_twingle_project_Sync(array $params): array { // sync project $result = _projectSync( - $project, - $project_from_twingle, - $twingleApi, - $params); + $project, + $project_from_twingle, + $twingleApi, + $params, + $pull + ); if (!$result['is_error'] == 0) { $errors[$result['id']] = $result['error_message']; $returnValues[$project->getId()] = @@ -457,6 +481,7 @@ function _pushProjectToTwingle(TwingleProject $project, * @param array $project_from_twingle * @param \CRM_TwingleCampaign_BAO_TwingleApiCall $twingleApi * @param array $params + * @param bool $pull Force pulling project from Twingle and update local campaign * * @return array * @throws \CiviCRM_API3_Exception @@ -464,11 +489,13 @@ function _pushProjectToTwingle(TwingleProject $project, function _projectSync(TwingleProject $project, array $project_from_twingle, TwingleApiCall $twingleApi, - array $params): array { + array $params, + bool $pull = FALSE): array { // If Twingle's version of the project is newer than the CiviCRM // TwingleProject campaign, update the campaign - if ($project_from_twingle['last_update'] > $project->lastUpdate()) { + if ($project_from_twingle['last_update'] > $project->lastUpdate() || + $pull) { return _updateProjectLocally($project_from_twingle, $project, $params, $twingleApi); } diff --git a/l10n/de_DE/LC_MESSAGES/twinglecampaign.mo b/l10n/de_DE/LC_MESSAGES/twinglecampaign.mo index e4a39ee1fe73b329e902527919b8bfda35ef13d4..47867c327cada245d4485c5c2c0ddb14b240bbfb 100644 GIT binary patch delta 6372 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 HE{*sPr(ISq delta 5625 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