diff --git a/modules/access_affinitygroup/access_affinitygroup.install b/modules/access_affinitygroup/access_affinitygroup.install index e857f2d7..da6eec35 100644 --- a/modules/access_affinitygroup/access_affinitygroup.install +++ b/modules/access_affinitygroup/access_affinitygroup.install @@ -25,7 +25,7 @@ function access_affinitygroup_update_10002() { // Get 'state' taxonomy term IDs for recruiting states. $recruiting_term = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadByProperties(['name' => 'recruiting']); $in_progress_recruiting_term = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadByProperties(['name' => 'In Progress and Recruiting']); - + $term_ids = []; if ($recruiting_term) { $term_ids[] = array_keys($recruiting_term)[0]; @@ -33,7 +33,7 @@ function access_affinitygroup_update_10002() { if ($in_progress_recruiting_term) { $term_ids[] = array_keys($in_progress_recruiting_term)[0]; } - + if (!empty($term_ids)) { // Get all mentorship nodes currently in recruiting states that are approved and published $query = \Drupal::entityQuery('node') @@ -43,15 +43,89 @@ function access_affinitygroup_update_10002() { ->condition('status', 1) ->accessCheck(FALSE); $existing_recruiting_nids = $query->execute(); - + // Set these as already notified to prevent sending emails for existing mentorships \Drupal::state()->set('access_affinitygroup.notified_mentorships', array_values($existing_recruiting_nids)); - + $count = count($existing_recruiting_nids); \Drupal::logger('access_affinitygroup')->info('Update 10002: Marked @count existing recruiting mentorships (approved and published) as already notified to prevent duplicate emails.', ['@count' => $count]); - + return "Marked $count existing recruiting mentorships (approved and published) as already notified."; } - + return 'No recruiting mentorships found to mark as notified.'; } + +/** + * Update user CC ids. + */ +function access_affinitygroup_update_10003() { + $connection = \Drupal::database(); + $query = $connection->select('user__field_constant_contact_id', 'cci'); + $query->fields('cci', ['entity_id', 'field_constant_contact_id_value']); + $result = $query->execute()->fetchAll(); + foreach ($result as $row) { + $user_id = $row->entity_id; + $cc_id = $row->field_constant_contact_id_value; + + $user_cc_id = [ + 'test' => '', + 'openondemand' => '', + 'support' => $cc_id, + ]; + + $user_cc_id = json_encode($user_cc_id); + + $query = \Drupal::database()->update('user__field_constant_contact_id') + ->fields([ + 'field_constant_contact_id_value' => $user_cc_id, + ]) + ->condition('entity_id', $user_id, '=') + ->execute(); + } +} + +/** + * Set forced token state. + */ +function access_affinitygroup_update_10004() { + \Drupal::state()->set('access_affinitygroup.forcedTokenSettings', NULL); +} + +/** + * Set Refresh token state. + */ +function access_affinitygroup_update_10005() { + $current_token = \Drupal::state()->get('access_affinitygroup.refresh_token'); + $new_token = [ + "support" => $current_token, + "openondemand" => '', + "test" => '', + ]; + $new_token = json_encode($new_token); + \Drupal::state()->set('access_affinitygroup.refresh_token', $new_token); +} + +/** + * Set forced token state. + */ +function access_affinitygroup_update_10006() { + // Get config setting 'access_affinitygroup.settings'. + $ag_config = \Drupal::configFactory()->getEditable('access_affinitygroup.settings'); + + // Get access_token + $access_token = $ag_config->get('access_token'); + + $new_token = [ + "support" => $access_token, + "openondemand" => '', + "test" => '', + ]; + $new_token = json_encode($new_token); + + \Drupal::state()->set('access_affinitygroup.access_token', $new_token); + + // Remove config item access_token from above. + $ag_config->set('access_token', NULL)->save(); +} + diff --git a/modules/access_affinitygroup/access_affinitygroup.module b/modules/access_affinitygroup/access_affinitygroup.module index b5806f79..bee8f1cd 100644 --- a/modules/access_affinitygroup/access_affinitygroup.module +++ b/modules/access_affinitygroup/access_affinitygroup.module @@ -240,7 +240,7 @@ function access_affinitygroup_entity_presave(EntityInterface $entity) { // Get all existing CC lists. $cca = new ConstantContactApi(); - $lists = $cca->apiCall('/contact_lists '); + $lists = $cca->apiCall('/contact_lists'); if (empty($lists)) { return; } @@ -270,7 +270,7 @@ function access_affinitygroup_entity_presave(EntityInterface $entity) { $post_data = json_encode($post_data); // Create Constant contact list named with AG title. - $created_list = $cca->apiCall('/contact_lists ', $post_data, 'POST'); + $created_list = $cca->apiCall('/contact_lists', $post_data, 'POST'); if (!empty($created_list)) { $list_id = $created_list->list_id ? Xss::filter($created_list->list_id) : ''; @@ -857,6 +857,8 @@ function makeListMembershipJSON($flagEntityId, $userDetails) { $ccIdField = $userDetails->get('field_constant_contact_id')->getValue(); if (!empty($ccIdField)) { $user_cc_id = $ccIdField[0]['value']; + $constantcontactapi = new ConstantContactApi(); + $user_cc_id = $constantcontactapi->getUserCcId($user_cc_id); } if (empty($user_cc_id)) { @@ -916,20 +918,50 @@ function access_affinitygroup_user_login(UserInterface $account) { if (!empty($field_val)) { $cca_user_id = $field_val[0]['value']; } + // If user did not already have the CC id, try to add to CC. - if (empty($cca_user_id)) { + if (empty($cca_user_id) || !json_validate($cca_user_id)) { + $user_cc_id = [ + 'test' => '', + 'openondemand' => '', + 'support' => '', + ]; + + $constantcontactapi = new ConstantContactApi(); + $env = $constantcontactapi->getEnvironment(); $firstName = $user_detail->get('field_user_first_name')->getString(); $lastName = $user_detail->get('field_user_last_name')->getString(); - $cca_user_id = addUserToConstantContact($current_user->getEmail(), $firstName, $lastName); - if (empty($cca_user_id)) { + + $user_cc_id[$env] = addUserToConstantContact($current_user->getEmail(), $firstName, $lastName); + + if (empty($user_cc_id[$env])) { showStatus("Could not add user to Constant Contact."); } else { - $user_detail->set('field_constant_contact_id', $cca_user_id); + $user_cc_id = json_encode($user_cc_id); + $user_detail->set('field_constant_contact_id', $user_cc_id); $user_detail->save(); } } else { + $constantcontactapi = new ConstantContactApi(); + $env = $constantcontactapi->getEnvironment(); + $user_cc_id = $user_detail->get('field_constant_contact_id')->getString(); + $user_cc_id = json_decode($user_cc_id, TRUE); + + if (empty($user_cc_id[$env])) { + $user_cc_id[$env] = addUserToConstantContact($current_user->getEmail(), $firstName, $lastName); + // Flatten if Array for $user_cc_id[$env] + $user_cc_id[$env] = is_array($user_cc_id[$env]) ? implode(',', $user_cc_id[$env]) : $user_cc_id[$env]; + if (empty($user_cc_id[$env])) { + showStatus("Could not add user to Constant Contact."); + } else { + $user_cc_id = json_encode($user_cc_id); + $user_detail->set('field_constant_contact_id', $user_cc_id); + $user_detail->save(); + } + } + // This else just for debugging in early stages // showStatus("Login and NOT attempting add of new constant contact id.");. } @@ -1107,23 +1139,19 @@ function access_affinitygroup_cron() { try { - // Make sure we are on the support domain, This is crucial for - // the constant contact connection. - $host = \Drupal::request()->getHttpHost(); - if ($host !== 'support.access-ci.org') { - \Drupal::logger('cron_affinitygroup')->debug("On $host: blocked Constant Contact cron"); - return; - } // 1. Refresh the Constant Contact Token if (shouldRun('token')) { $currentTime = \Drupal::time()->getCurrentTime(); \Drupal::state()->set('access_affinitygroup.crontime-t', $currentTime); - \Drupal::logger('access_affinitygroup')->notice('Cron: token refresh ' . date("Y-m-d H:i:s", $currentTime) . " on $host"); + \Drupal::logger('access_affinitygroup')->notice('Cron: token refresh ' . date("Y-m-d H:i:s", $currentTime)); - $cca = new ConstantContactApi(); - $cca->newToken(); + $support = new ConstantContactApi('support'); + $support->newToken(); + + $ood = new ConstantContactApi('openondemand'); + $ood->newToken(); } // 2. call xdusage api to get users and create/update their diff --git a/modules/access_affinitygroup/src/Commands/AffinityGroupCommands.php b/modules/access_affinitygroup/src/Commands/AffinityGroupCommands.php index c1ddf58e..3c8b0520 100644 --- a/modules/access_affinitygroup/src/Commands/AffinityGroupCommands.php +++ b/modules/access_affinitygroup/src/Commands/AffinityGroupCommands.php @@ -72,9 +72,13 @@ public function initConstantContact() { $this->output()->writeln($last_name); // Get the Constant Contact id for the User. + $env = $cca->getEnvironment(); + $field_val = $user->get('field_constant_contact_id')->getValue(); if (!empty($field_val) && $field_val != 0) { $cc_id = $field_val[0]['value']; + $cc_id = json_decode($cc_id, TRUE); + $cc_id = $cc_id[$env]; $this->output()->writeln($first_name . ' ' . $last_name . ' already has cc id: ' . $cc_id); } else { @@ -92,7 +96,16 @@ public function initConstantContact() { usleep(500); } $this->output()->writeln($cc_id); - $user->set('field_constant_contact_id', $cc_id); + + $user_cc_id = [ + 'test' => '', + 'openondemand' => '', + 'support' => '', + ]; + $user_cc_id[$env] = $cc_id; + $user_cc_id = json_encode($user_cc_id); + + $user->set('field_constant_contact_id', $user_cc_id); $user->save(); $this->output()->writeln('Added ' . $first_name . ' ' . $last_name); } @@ -126,6 +139,8 @@ public function showAffinityGroups(string $agName = '', $options = ['uidonly' => $uidOnly = $options['uidonly']; $headOnly = $options['headonly']; + $cca = new ConstantContactApi(); + // Get all the Affinity Groups. $agCount = 0; $nids = \Drupal::entityQuery('node') @@ -203,7 +218,18 @@ public function showAffinityGroups(string $agName = '', $options = ['uidonly' => // Get the Constant Contact id for the User. $field_val = $user->get('field_constant_contact_id')->getValue(); if (!empty($field_val) && $field_val != 0) { + // Get the Constant Contact id for the User. + $env = $cca->getEnvironment(); + $cc_id = $field_val[0]['value']; + $cc_id = json_decode($cc_id, TRUE); + if (isset($cc_id[$env])) { + $cc_id = $cc_id[$env]; + } + else { + $cc_id = 'NO cc id for ' . $env; + } + } $this->output()->writeln('cc id: ' . $cc_id); } diff --git a/modules/access_affinitygroup/src/Form/ConstantContact.php b/modules/access_affinitygroup/src/Form/ConstantContact.php index a9856818..6602d827 100644 --- a/modules/access_affinitygroup/src/Form/ConstantContact.php +++ b/modules/access_affinitygroup/src/Form/ConstantContact.php @@ -32,17 +32,21 @@ public function buildForm(array $form, FormStateInterface $form_state) { $noConstantContactCalls = \Drupal::configFactory()->getEditable('access_affinitygroup.settings')->get('noConstantContactCalls'); + $forcedTokenSettings = \Drupal::state()->get('access_affinitygroup.forcedTokenSettings'); + $supportToken = $forcedTokenSettings == 'support' ? 1 : 0; + $openondemandToken = $forcedTokenSettings == 'openondemand' ? 1 : 0; + $testToken = $forcedTokenSettings == 'test' ? 1 : 0; + $request = \Drupal::request(); $code = $request->get('code'); $refresh_token = $request->get('refresh_token'); + $cca = new ConstantContactApi(); if ($refresh_token) { - $cca = new ConstantContactApi(); $cca->newToken(); } if ($code) { - $cca = new ConstantContactApi(); $cca->initializeToken($code); } @@ -73,9 +77,17 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#description' => $this->t('Select Constant Contact permissions.'), ]; + $environment = $cca->getEnvironment(); + + $form['clear'] = [ + '#type' => 'submit', + '#value' => $this->t('Clear tokens for') . ' ' . $environment, + '#submit' => [[$this, 'clearTokens']], + ]; + $form['submit'] = [ '#type' => 'submit', - '#value' => $this->t('Authorize App'), + '#value' => $this->t('Authorize App on') . ' ' . $environment, '#submit' => [[$this, 'submitForm']], ]; @@ -98,6 +110,40 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#value' => $this->t('Save Disable Setting'), '#submit' => [[$this, 'doSaveDisableCC']], ]; + + $form['force_token_title'] = [ + '#markup' => '

' . $this->t('Force Token') . '

', + ]; + + $form['support'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Access Support'), + '#description' => $this->t('This will force the access support token'), + '#default_value' => $supportToken, + ]; + + $form['openondemand'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Open On Demand'), + '#description' => $this->t('This will force the open on demand token'), + '#default_value' => $openondemandToken, + ]; + + $form['test'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Test'), + '#description' => $this->t('This will force the test token'), + '#default_value' => $testToken, + ]; + + $form['force_token_save'] = [ + '#type' => 'submit', + '#description' => $this->t('Unchecked is the normal value.'), + '#value' => $this->t('Save forced token settings'), + '#submit' => [[$this, 'doSaveTokenSet']], + ]; + + $form['y5'] = [ '#markup' => '

Generate Weekly Digest

', ]; @@ -339,6 +385,17 @@ public function validateForm(array &$form, FormStateInterface $form_state) { } } + /** + * {@inheritdoc} + */ + public function clearTokens(array &$form, FormStateInterface $form_state) { + $cc = new ConstantContactApi(); + $cc->clearTokens(); + + \Drupal::messenger()->addMessage(t('Constant Contact tokens cleared.')); + + } + /** * {@inheritdoc} */ @@ -350,13 +407,11 @@ public function submitForm(array &$form, FormStateInterface $form_state) { } } $cc = new ConstantContactApi(); - $key = trim(\Drupal::service('key.repository')->getKey('constant_contact_client_id')->getKeyValue()); - $token = urlencode($key); $host = \Drupal::request()->getSchemeAndHttpHost(); $redirectURI = urlencode("$host/admin/services/constantcontact-token"); $scope = urlencode(rtrim($selected_scope)); $state = uniqid(); - $response = new RedirectResponse($cc->getAuthorizationURL($token, $redirectURI, $scope, $state)); + $response = new RedirectResponse($cc->getAuthorizationURL($redirectURI, $scope, $state)); $response->send(); parent::submitForm($form, $form_state); } @@ -370,6 +425,33 @@ public function doSaveDisableCC(array &$form, FormStateInterface $form_state) { $config->save(); } + /** + * Save config setting access_affinitygroup.settings.noConstantContactCalls according to checkbox value. + */ + public function doSaveTokenSet(array &$form, FormStateInterface $form_state) { + $forcedTokenSettings = [ + 'support' => $form_state->getValue('support'), + 'openondemand' => $form_state->getValue('openondemand'), + 'test' => $form_state->getValue('test'), + ]; + + $oneset = FALSE; + \Drupal::state()->set('access_affinitygroup.forcedTokenSettings', NULL); + + foreach ($forcedTokenSettings as $key => $value) { + if ($value) { + if ($oneset) { + \Drupal::messenger()->addError(t('Only one token setting can be set to TRUE.')); + return; + } + + \Drupal::state()->set('access_affinitygroup.forcedTokenSettings', $key); + $oneset = TRUE; + } + } + + } + /** * Save state variables for running and testing the allocations import cron job according to checkbox values. */ diff --git a/modules/access_affinitygroup/src/Plugin/AllocationsUsersImport.php b/modules/access_affinitygroup/src/Plugin/AllocationsUsersImport.php index c190faf2..c9c9f24d 100644 --- a/modules/access_affinitygroup/src/Plugin/AllocationsUsersImport.php +++ b/modules/access_affinitygroup/src/Plugin/AllocationsUsersImport.php @@ -587,7 +587,13 @@ private function cronAddToConstantContact($u, $uEmail, $firstName, $lastName) { return FALSE; } else { - $u->set('field_constant_contact_id', $ccId); + $user_cc_id = [ + 'test' => '', + 'openondemand' => '', + 'support' => $ccId, + ]; + $user_cc_id = json_encode($user_cc_id); + $u->set('field_constant_contact_id', $user_cc_id); $u->save(); $this->collectCronLog("Id from Constant Contact: $uEmail", 'd'); return TRUE; @@ -761,6 +767,8 @@ private function userDetailUpdates($u, $a) { if (!empty($ccIdField)) { $ccId = $ccIdField[0]['value']; if (!empty($ccId)) { + $ccId = json_decode($ccId, TRUE); + $ccId = $ccId['support']; if (!$this->batchNoCC && !$this->batchNoUserDetSave) { $cca = new ConstantContactApi(); $cca->setSupressErrDisplay(TRUE); @@ -963,6 +971,8 @@ public function syncAGandCC($agBegin = 0, $agEnd = 1000, $verbose = FALSE) { $field_val = $user->get('field_constant_contact_id')->getValue(); if (!empty($field_val) && $field_val != 0) { $ccId = $field_val[0]['value']; + $ccId = json_decode($ccId, TRUE); + $ccId = $ccId['support']; // Check to see of it's a good CC Id. // preventing attempts to work with an obfuscated CC Id. if (strlen($ccId) == 36) { diff --git a/modules/access_affinitygroup/src/Plugin/ConstantContactApi.php b/modules/access_affinitygroup/src/Plugin/ConstantContactApi.php index 1a9ea45e..3f54dba5 100644 --- a/modules/access_affinitygroup/src/Plugin/ConstantContactApi.php +++ b/modules/access_affinitygroup/src/Plugin/ConstantContactApi.php @@ -22,6 +22,11 @@ class ConstantContactApi { */ private $refreshToken; + /** + * Return environment. + */ + private $environment; + /** * Return clientId. */ @@ -39,33 +44,47 @@ class ConstantContactApi { */ private $supressErrDisplay; + /** + * Return cc key. + */ + private $cc_key; + + /** + * Return key secret. + */ + private $key_secret; + /** * Function to sort the curl headers. * Sets the clientId and the clientSecret. If they are not present, sets to empty. */ - public function __construct() { + public function __construct($env = NULL) { try { - $config_factory = \Drupal::configFactory(); - $this->configSettings = $config_factory->getEditable('access_affinitygroup.settings'); - $this->accessToken = $this->configSettings->get('access_token'); - $this->refreshToken = \Drupal::state()->get('access_affinitygroup.refresh_token'); + if ($env) { + $this->environment = $env; + } else { + $this->getEnvironment(); + } + $this->accessToken = $this->getAppToken(); + $this->refreshToken = $this->getRefreshToken(); + $this->getKey(); - $cc_key = \Drupal::service('key.repository')->getKey('constant_contact_client_id')->getKeyValue(); + $cc_key = $this->cc_key; if (empty($cc_key)) { \Drupal::logger('access_affinitygroup')->error('Constant Contact: client id not in repository.'); } else { - $cc_key = urlencode(trim($cc_key)); + $cc_key = $cc_key; } $this->clientId = $cc_key; - $key_secret = \Drupal::service('key.repository')->getKey('constant_contact_client_secret')->getKeyValue(); + $key_secret = $this->key_secret; if (empty($key_secret)) { \Drupal::logger('access_affinitygroup')->error('Constant Contact: client secret not in repository.'); } else { - $key_secret = urlencode(trim($key_secret)); + $key_secret = $key_secret; } $this->clientSecret = $key_secret; @@ -112,8 +131,6 @@ public function setSupressErrDisplay($v) { /** * @param $redirectURI * - URL Encoded Redirect URI - * @param $clientId - * - API Key * @param $scope * - URL encoded, plus sign delimited list of scopes that your * application requires. The 'offline_access' scope needed to request a @@ -123,14 +140,65 @@ public function setSupressErrDisplay($v) { * application state * @return string - Full Authorization URL */ - public function getAuthorizationURL($clientId, $redirectURI, $scope, $state) { + public function getAuthorizationURL($redirectURI, $scope, $state) { // Create authorization URL. $baseURL = "https://authz.constantcontact.com/oauth2/default/v1/authorize"; - $authURL = $baseURL . "?client_id=" . $clientId . "&scope=" . $scope . "+offline_access&response_type=code&state=" . $state . "&redirect_uri=" . $redirectURI; + $authURL = $baseURL . "?client_id=" . $this->cc_key . "&scope=" . $scope . "+offline_access&response_type=code&state=" . $state . "&redirect_uri=" . $redirectURI; return $authURL; } + /** + * Get the Constant Contact key and secret. + */ + private function getKey() { + $keys = \Drupal::service('key.repository')->getKey('constant_contact_json')->getKeyValues(); + $env = $this->environment; + + $cc_key = json_decode($keys[0], true)[$env]['id']; + $key_secret = json_decode($keys[0], true)[$env]['secret']; + + $this->cc_key = urlencode(trim($cc_key)); + $this->key_secret = urlencode(trim($key_secret)); + } + + /** + * Get the current environment. + */ + public function getEnvironment() { + $env = getenv('PANTHEON_ENVIRONMENT'); + $forcedToken = \Drupal::state()->get('access_affinitygroup.forcedTokenSettings'); + + if ($env == 'local') { + $env = 'test'; + } + else { + $current_domain_name = \Drupal::service('access_misc.sitetools')->getDomain(); + + if ($current_domain_name == 'open-ondemand') { + $env = 'openondemand'; + } + else { + $env = 'support'; + } + } + + $env = $forcedToken ? $forcedToken : $env; + + $this->environment = $env; + + return $env; + } + + /** + * Get the user CC id. + */ + public function getUserCcId($user_cc_json) { + $env = $this->environment; + $user_cc_json = json_decode($user_cc_json, TRUE); + return $user_cc_json[$env] ?? 0; + } + /** * Initialize Constant Contact Token. */ @@ -203,17 +271,17 @@ public function newToken() { $httpCode = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); - $host = \Drupal::request()->getSchemeAndHttpHost(); + $env = $this->environment; if (!isset($result->error)) { $this->setAccessToken($result->access_token); $this->setRefreshToken($result->refresh_token); - \Drupal::logger('access_affinitygroup')->notice("Constant Contact: new access_token and refresh_token stored $host"); + \Drupal::logger('access_affinitygroup')->notice("Constant Contact: new access_token and refresh_token stored $env"); \Drupal::messenger()->addMessage("Constant Contact: new access_token and refresh_token stored"); } else { - \Drupal::logger('access_affinitygroup')->notice("New token httpCode: $httpCode"); - \Drupal::logger('access_affinitygroup')->error("New token error; host $host"); + \Drupal::logger('access_affinitygroup')->notice("Token httpCode: $httpCode"); + \Drupal::logger('access_affinitygroup')->error("Token Error: env $env"); $this->apiError($result->error, $result->error_description); $policy = 'affinitygroup'; @@ -450,18 +518,63 @@ public function getConnectionStatus() { * Save new access_token. */ private function setAccessToken($access_token) { + $tokenjson = \Drupal::state()->get('access_affinitygroup.access_token'); + $env = $this->environment; + + $token_array = $tokenjson ? json_decode($tokenjson, TRUE) : []; + $token_array[$env] = $access_token; + $access_token = json_encode($token_array); + $this->accessToken = $access_token; - $this->configSettings->set('access_token', $access_token); - $this->configSettings->save(); + \Drupal::state()->set('access_affinitygroup.access_token', $access_token); + } + + /** + * Get access_token. + */ + private function getAppToken() { + $tokenjson = \Drupal::state()->get('access_affinitygroup.access_token'); + $env = $this->environment; + + $this->accessToken = json_decode($tokenjson, TRUE)[$env]; + + return $this->accessToken; + } + + /** + * Get refresh_token. + */ + private function getRefreshToken() { + $tokenjson = \Drupal::state()->get('access_affinitygroup.refresh_token'); + $env = $this->environment; + + $this->refreshToken = json_decode($tokenjson, TRUE)[$env]; + + return $this->refreshToken; } + /** + * Get clear tokens. + */ + public function clearTokens() { + $this->setRefreshToken(''); + $this->setAccessToken(''); + } + + /** * Save new refresh_token. */ private function setRefreshToken($refresh_token) { + $tokenjson = \Drupal::state()->get('access_affinitygroup.refresh_token'); + $env = $this->environment; + + $token_array = $tokenjson ? json_decode($tokenjson, TRUE) : []; + $token_array[$env] = $refresh_token; + $refresh_token = json_encode($token_array); + $this->refreshToken = $refresh_token; \Drupal::state()->set('access_affinitygroup.refresh_token', $refresh_token); - } /*