Skip to content

Instantly share code, notes, and snippets.

@jackrabbithanna
Created September 10, 2024 21:32
Show Gist options
  • Save jackrabbithanna/f808b3aa6b93671e483d733b94051a26 to your computer and use it in GitHub Desktop.
Save jackrabbithanna/f808b3aa6b93671e483d733b94051a26 to your computer and use it in GitHub Desktop.
<?php
/**
* @file
* Sync civicrm user preferences with Drupal groups.
*/
use Drupal\Core\Database\Database;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\group\Entity\GroupRelationshipInterface;
use Drupal\user\UserInterface;
/**
* Utility function to get matched contact id given uid.
*
* @param int $uid
* The uid.
*
* @return int
* The contact id
*/
function civi_group_to_drupal_group_sync_contact_id_from_uid($uid) {
$contact_id = 0;
\Drupal::service('civicrm')->initialize();
// Eepro.
$domain_id = 2;
$uf_match_results = civicrm_api3('UfMatch', 'get', [
'sequential' => TRUE,
'domain_id' => $domain_id,
'uf_id' => $uid,
]);
if (!empty($uf_match_results['values'][0]['contact_id'])) {
$contact_id = $uf_match_results['values'][0]['contact_id'];
}
return $contact_id;
}
/**
* Implements hook_user_login().
*/
function civi_group_to_drupal_group_sync_user_login(UserInterface $account) {
try {
$uid = $account->id();
\Drupal::service('civicrm')->initialize();
$contact_id = civi_group_to_drupal_group_sync_contact_id_from_uid($uid);
if (!empty($contact_id)) {
// Query for all groups with a value for field_related_civicrm_group.
$group_storage = \Drupal::entityTypeManager()->getStorage('group');
$query = \Drupal::entityQuery('group');
$query->accessCheck(FALSE);
$query->exists('field_related_civicrm_group');
$group_ids = $query->execute();
$civi_groups_mapping = [];
if (!empty($group_ids)) {
$groups = $group_storage->loadMultiple(array_keys($group_ids));
foreach ($groups as $group) {
if ($group->hasField('field_related_civicrm_group') && !empty($group->field_related_civicrm_group->target_id)) {
$civi_groups_mapping[$group->field_related_civicrm_group->target_id] = $group->id();
}
}
if (!empty($civi_groups_mapping)) {
// Query for group_contact records, for the contact.
$civi_groups = array_keys($civi_groups_mapping);
$civi_db_connection = Database::getConnection('default', 'civicrm');
$civi_query = $civi_db_connection->select('civicrm_contact', 'c');
$civi_query->fields('gc', ['group_id']);
$civi_query->leftJoin('civicrm_group_contact', 'gc', 'gc.contact_id = c.id');
$civi_query->condition('gc.contact_id', $contact_id, '=');
$civi_query->condition('gc.status', 'Added', '=');
$civi_query->condition('gc.group_id', $civi_groups, 'IN');
$civi_query_result = $civi_query->execute()->fetchAllAssoc('group_id', \PDO::FETCH_ASSOC);
$contacts_civi_groups = [];
if (!empty($civi_query_result)) {
$contacts_civi_groups = array_keys($civi_query_result);
}
// Now for each Drupal group, add or remove user appropriately.
$group_membership_loader = \Drupal::service('group.membership_loader');
foreach ($civi_groups_mapping as $c_group_id => $d_group_id) {
$group = $groups[$d_group_id];
$group_membership = $group_membership_loader->load($group, $account);
// If contact in Civi group, should be a member in the Drupal group.
if (in_array($c_group_id, $contacts_civi_groups)) {
if (empty($group_membership)) {
$group->addMember($account, ['group_roles' => ['member']]);
}
}
else {
// If in the Drupal group, remove membership.
if (!empty($group_membership)) {
$group->removeMember($account);
}
}
}
}
}
}
}
catch (\Exception $e) {
\Drupal::logger('civi_group_to_drupal_group_sync')->error($e->getMessage());
}
}
/**
* Implements hook_ENTITY_TYPE_insert().
*/
function civi_group_to_drupal_group_sync_group_content_insert(GroupRelationshipInterface $entity) {
try {
$bundle = $entity->bundle();
$group_membership_bundles = [
'public_group-group_membership',
'private_group-group_membership',
];
// Check bundle.
if (in_array($bundle, $group_membership_bundles)) {
// Get group, and check reference field.
$group = $entity->getGroup();
if ($group && $group->hasField('field_related_civicrm_group') && !empty($group->field_related_civicrm_group->target_id)) {
$civi_group_id = $group->field_related_civicrm_group->target_id;
// Get group membership uid.
$uid = $entity->getEntityId();
// Get contact id.
$contact_id = civi_group_to_drupal_group_sync_contact_id_from_uid($uid);
if (!empty($contact_id)) {
\Drupal::service('civicrm')->initialize();
// Check if contact is in group.
$cg_lookup_result = civicrm_api3('GroupContact', 'get', [
'contact_id' => $contact_id,
'group_id' => $civi_group_id,
]);
// Create group contact record if necessary.
if (empty($cg_lookup_result['count'])) {
$cg_create_result = civicrm_api3('GroupContact', 'create', [
'contact_id' => $contact_id,
'group_id' => $civi_group_id,
]);
}
}
}
}
}
catch (\Exception $e) {
\Drupal::logger('civi_group_to_drupal_group_sync')->error($e->getMessage());
}
}
/**
* Implements hook_ENTITY_TYPE_delete().
*/
function civi_group_to_drupal_group_sync_group_content_delete(GroupRelationshipInterface $entity) {
try {
$bundle = $entity->bundle();
$group_membership_bundles = [
'public_group-group_membership',
'private_group-group_membership',
];
// Check bundle.
if (in_array($bundle, $group_membership_bundles)) {
// Get group, and check reference field.
$group = $entity->getGroup();
if ($group && $group->hasField('field_related_civicrm_group') && !empty($group->field_related_civicrm_group->target_id)) {
$civi_group_id = $group->field_related_civicrm_group->target_id;
// Get group membership uid.
$uid = $entity->getEntityId();
// Get contact id.
$contact_id = civi_group_to_drupal_group_sync_contact_id_from_uid($uid);
if (!empty($contact_id)) {
\Drupal::service('civicrm')->initialize();
// Check if contact is in group.
$cg_lookup_result = civicrm_api3('GroupContact', 'get', [
'contact_id' => $contact_id,
'group_id' => $civi_group_id,
]);
// Delete group contact record if necessary.
if (!empty($cg_lookup_result['count'])) {
$cg_create_result = civicrm_api3('GroupContact', 'delete', [
'contact_id' => $contact_id,
'group_id' => $civi_group_id,
]);
}
}
}
}
}
catch (\Exception $e) {
\Drupal::logger('civi_group_to_drupal_group_sync')->error($e->getMessage());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment