civicrm_entity-8.x-3.0-beta1/civicrm_entity.module
civicrm_entity.module
<?php /** * @file * Module file for the CiviCRM Entity module. */ use Drupal\civicrm_entity\CivicrmEntityAccessHandler; use Drupal\civicrm_entity\CivicrmEntityListBuilder; use Drupal\civicrm_entity\CiviCrmEntityViewBuilder; use Drupal\civicrm_entity\CivicrmEntityViewsData; use Drupal\civicrm_entity\CiviEntityStorage; use Drupal\civicrm_entity\Entity\CivicrmEntity; use Drupal\civicrm_entity\Entity\Sql\CivicrmEntityStorageSchema; use Drupal\civicrm_entity\Form\CivicrmEntityForm; use Drupal\civicrm_entity\Routing\CiviCrmEntityRouteProvider; use Drupal\civicrm_entity\SupportedEntities; use Drupal\Core\Database\Query\AlterableInterface; use Drupal\Core\Entity\ContentEntityDeleteForm; use Drupal\Core\Entity\ContentEntityType; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityDisplayRepositoryInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Render\Element; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\field\Entity\FieldConfig; use Drupal\field\FieldConfigInterface; use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay; use Drupal\views\ViewExecutable; use Drupal\views\Plugin\views\query\QueryPluginBase; use Drupal\Core\Database\Database; use Drupal\Core\Entity\Display\EntityDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\civicrm_entity\Plugin\search_api\datasource\CivicrmEntity as DatasourceCivicrmEntity; use Drupal\Core\Field\Entity\BaseFieldOverride; /** * Implements hook_theme(). */ function civicrm_entity_theme() { return [ 'civicrm_entity_entity_form' => [ 'render element' => 'form', ], 'civicrm_entity' => [ 'render element' => 'elements', ], ]; } /** * Implements hook_entity_type_build(). * * Populates supported CiviCRM Entity definitions. */ function civicrm_entity_entity_type_build(array &$entity_types) { $logger = \Drupal::logger('civicrm-entity'); $supported_entities = SupportedEntities::getInfo(); $config = \Drupal::config('civicrm_entity.settings'); $enabled_entity_types = $config->get('enabled_entity_types') ?: []; $enable_links_per_type = $config->get('enable_links_per_type') ?: []; foreach ($supported_entities as $entity_type_id => $civicrm_entity_info) { $clean_entity_type_id = str_replace('_', '-', $entity_type_id); $civicrm_entity_name = $civicrm_entity_info['civicrm entity name']; if (empty($civicrm_entity_info['label property'])) { $logger->debug(sprintf('Missing label property: %s', $entity_type_id)); continue; } $entity_type_info = [ 'provider' => 'civicrm_entity', 'class' => CivicrmEntity::class, 'originalClass' => CivicrmEntity::class, 'id' => $entity_type_id, 'component' => $civicrm_entity_info['component'] ?? NULL, 'civicrm_entity' => $civicrm_entity_name, 'civicrm_entity_ui_exposed' => in_array($entity_type_id, $enabled_entity_types), 'label' => new TranslatableMarkup('CiviCRM :name', [':name' => $civicrm_entity_info['civicrm entity label']]), // @todo add label_singular // @todo add label_plural // @todo add label_count 'entity_keys' => [ 'id' => 'id', 'label' => $civicrm_entity_info['label property'], ], 'base_table' => $entity_type_id, 'admin_permission' => 'administer civicrm entity', 'permission_granularity' => 'entity_type', 'handlers' => [ 'storage' => CiviEntityStorage::class, 'access' => CivicrmEntityAccessHandler::class, 'views_data' => CivicrmEntityViewsData::class, 'storage_schema' => CivicrmEntityStorageSchema::class, ], ]; if (in_array($entity_type_id, $enabled_entity_types)) { $entity_type_info = array_merge_recursive($entity_type_info, [ 'handlers' => [ 'list_builder' => CivicrmEntityListBuilder::class, 'view_builder' => CiviCrmEntityViewBuilder::class, 'route_provider' => [ 'default' => CiviCrmEntityRouteProvider::class, ], 'form' => [ 'default' => CivicrmEntityForm::class, 'add' => CivicrmEntityForm::class, 'edit' => CivicrmEntityForm::class, 'delete' => ContentEntityDeleteForm::class, ], ], // Generate route paths. 'links' => [ 'canonical' => sprintf('/%s/{%s}', $clean_entity_type_id, $entity_type_id), 'delete-form' => sprintf('/%s/{%s}/delete', $clean_entity_type_id, $entity_type_id), 'edit-form' => sprintf('/%s/{%s}/edit', $clean_entity_type_id, $entity_type_id), 'add-form' => sprintf('/%s/add', $clean_entity_type_id, $entity_type_id), 'collection' => sprintf('/admin/structure/civicrm-entity/%s', $clean_entity_type_id), ], 'field_ui_base_route' => "entity.$entity_type_id.collection", ]); if (!empty($enable_links_per_type) && in_array($entity_type_id, array_keys($enable_links_per_type))) { $enable_links = array_filter($enable_links_per_type[$entity_type_id]['values']); if (!in_array('view', $enable_links)) { unset($entity_type_info['links']['canonical']); } if (!in_array('delete', $enable_links)) { unset($entity_type_info['links']['delete-form']); } if (!in_array('edit', $enable_links)) { unset($entity_type_info['links']['edit-form']); } if (!in_array('add', $enable_links)) { unset($entity_type_info['links']['add-form']); } } if ($config->get('disable_links')) { unset( $entity_type_info['links']['canonical'], $entity_type_info['links']['delete-form'], $entity_type_info['links']['edit-form'], $entity_type_info['links']['add-form'], ); } } // If this entity has bundle support, we define the bundle field as "bundle" // and will use the "bundle property" as the field to fetch field options // from CiviCRM with. // // @see civicrm_entity_entity_bundle_info() // @see \Drupal\civicrm_entity\Entity\CivicrmEntity::baseFieldDefinitions() if (!empty($civicrm_entity_info['bundle property'])) { $entity_type_info['entity_keys']['bundle'] = 'bundle'; $entity_type_info['civicrm_bundle_property'] = $civicrm_entity_info['bundle property']; if (isset($entity_type_info['links']['add-form'])) { // For entities with bundles that are exposed, add the `bundle` key to // the add-form route. In CiviCrmEntityRouteProvider::getAddFormRoute // we default the value, so that it isn't actually required in the URL. $entity_type_info['links']['add-form'] = sprintf('%s/{%s}', $entity_type_info['links']['add-form'], $entity_type_info['entity_keys']['bundle']); } } $entity_types[$entity_type_id] = new ContentEntityType($entity_type_info); } } /** * Implements hook_entity_bundle_info(). */ function civicrm_entity_entity_bundle_info() { $transliteration = \Drupal::transliteration(); /** @var \Drupal\civicrm_entity\CiviCrmApiInterface $civicrm_api */ $civicrm_api = \Drupal::service('civicrm_entity.api'); $bundles = []; $entity_types_with_bundles = array_filter(SupportedEntities::getInfo(), static function (array $civicrm_entity_info) { return !empty($civicrm_entity_info['bundle property']); }); foreach ($entity_types_with_bundles as $entity_type_id => $civicrm_entity_info) { // We keep a bundle that is the same as the entity type ID. This allows us // to create fields as if this entity has no bundles. $bundles[$entity_type_id] = [ $entity_type_id => [ 'label' => $civicrm_entity_info['civicrm entity label'], ], ]; $options = $civicrm_api->getOptions($civicrm_entity_info['civicrm entity name'], $civicrm_entity_info['bundle property']); foreach ($options as $option) { $machine_name = SupportedEntities::optionToMachineName($option, $transliteration); $bundles[$entity_type_id][$machine_name]['label'] = $option; } } return $bundles; } /** * Implements hook_entity_bundle_field_info(). * * This ensures CiviCRM Entity entity types have their field config instances * across all bundles. It's a copy of the Field module's logic, but clones * field config definitions. * * @see field_entity_bundle_field_info() */ function civicrm_entity_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) { $result = []; if ($entity_type->get('civicrm_entity_ui_exposed') && $entity_type->hasKey('bundle')) { // Query by filtering on the ID as this is more efficient than filtering // on the entity_type property directly. $ids = \Drupal::entityQuery('field_config') ->condition('id', $entity_type->id() . '.', 'STARTS_WITH') ->accessCheck(FALSE) ->execute(); // Fetch all fields and key them by field name. $field_configs = FieldConfig::loadMultiple($ids); // Clone the field configs, so that we can modify them and change the // target bundle type without manipulating the statically cached entries // in the entity storage;. $cloned_field_configs = array_map(static function (FieldConfigInterface $field) use ($bundle) { $cloned = clone $field; $cloned->set('bundle', $bundle); return $cloned; }, $field_configs); foreach ($cloned_field_configs as $field_instance) { $result[$field_instance->getName()] = $field_instance; } } // Ensure all fields have a definition. if ($entity_type->get('civicrm_entity_ui_exposed') && $entity_type->hasKey('bundle')) { foreach ($base_field_definitions as $field_name => $definition) { if (isset($result[$field_name])) { continue; } $field = BaseFieldOverride::createFromBaseFieldDefinition($base_field_definitions[$field_name], $bundle); $result[$field_name] = $field; } } return $result; } /** * Implements hook_entity_view_display_alter(). * * There is no way to handle this in the entity type's view builder. */ function civicrm_entity_entity_view_display_alter(EntityViewDisplayInterface $display, array $context) { $entity_type = \Drupal::entityTypeManager()->getDefinition($context['entity_type']); assert($entity_type !== NULL); if ($entity_type->get('civicrm_entity') && $entity_type->hasKey('bundle')) { $entity_display_repository = \Drupal::service('entity_display.repository'); assert($entity_display_repository instanceof EntityDisplayRepositoryInterface); $entity_view_mode_ids = array_keys($entity_display_repository->getViewModeOptions($entity_type->id())); $view_mode = !empty($context['view_mode']) && in_array($context['view_mode'], $entity_view_mode_ids) ? $context['view_mode'] : $entity_display_repository::DEFAULT_DISPLAY_MODE; $root_display = $entity_display_repository->getViewDisplay( $entity_type->id(), $entity_type->id(), $view_mode ); $display->set('content', $root_display->get('content')); $display->set('hidden', $root_display->get('hidden')); if ($root_display instanceof LayoutBuilderEntityViewDisplay) { $layout_builder_settings = $root_display->getThirdPartySettings('layout_builder'); foreach ($layout_builder_settings as $setting_key => $setting) { $display->setThirdPartySetting('layout_builder', $setting_key, $setting); } } $ds_settings = $root_display->getThirdPartySettings('ds'); if (!empty($ds_settings) && is_array($ds_settings)) { foreach ($ds_settings as $setting_key => $setting) { $display->setThirdPartySetting('ds', $setting_key, $setting); } } } } /** * Implements hook_entity_view_alter(). */ function civicrm_entity_entity_view_alter(array &$build, EntityInterface $entity, EntityDisplayInterface $display) { $entity_type = $entity->getEntityType(); if ($entity_type->get('civicrm_entity') && $entity_type->hasKey('bundle') && \Drupal::moduleHandler()->moduleExists('field_group')) { $entity_display_repository = \Drupal::service('entity_display.repository'); $entity_view_mode_ids = array_keys($entity_display_repository->getViewModeOptions($entity_type->id())); $context = [ 'entity_type' => $display->getTargetEntityTypeId(), 'bundle' => $entity_type->id(), 'entity' => $entity, 'display_context' => 'view', 'mode' => in_array($display->getMode(), $entity_view_mode_ids) ? $display->getMode() : $entity_display_repository::DEFAULT_DISPLAY_MODE, ]; field_group_attach_groups($build, $context); } } /** * Implements hook_form_alter(). */ function civicrm_entity_form_alter(array &$form, FormStateInterface $form_state, $form_id) { $form_object = $form_state->getFormObject(); if ($form_object instanceof CivicrmEntityForm) { /** * @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */ $storage = $form_state->getStorage(); if (!empty($storage['form_display'])) { $form_display = $storage['form_display']; $entity = $form_object->getEntity(); if ($entity->getEntityType()->hasKey('bundle') && \Drupal::moduleHandler()->moduleExists('field_group')) { $context = [ 'entity_type' => $entity->getEntityTypeId(), 'bundle' => $entity->getEntityTypeId(), 'entity' => $entity, 'context' => 'form', 'display_context' => 'form', 'mode' => $form_display->getMode(), ]; field_group_attach_groups($form, $context); } } } } /** * Implements hook_module_implements_alter(). */ function civicrm_entity_module_implements_alter(&$implementations, $hook) { switch ($hook) { case 'form_alter': $group = $implementations['civicrm_entity']; unset($implementations['civicrm_entity']); $implementations['civicrm_entity'] = $group; break; } } /** * Implements callback_allowed_values_function(). * * Provides the pseudoconstant values for CiviCRM entity fields. * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition * The field storage definition. * @param \Drupal\Core\Entity\FieldableEntityInterface|null $entity * The entity. * @param bool $cacheable * If the options are cacheable. * * @return array * The array of field options. */ function civicrm_entity_pseudoconstant_options(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL, &$cacheable = NULL) { /** @var \Drupal\civicrm_entity\CiviCrmApiInterface $civicrm_api */ $civicrm_api = \Drupal::service('civicrm_entity.api'); $entity_type = \Drupal::entityTypeManager()->getDefinition($definition->getTargetEntityTypeId()); $options = $civicrm_api->getOptions($entity_type->get('civicrm_entity'), $definition->getName()); return $options; } /** * Implements hook_preprocess(). */ function template_preprocess_civicrm_entity(&$variables) { // Add fields as content to template. $variables += ['content' => []]; foreach (Element::children($variables['elements']) as $key) { $variables['content'][$key] = $variables['elements'][$key]; } // Add the view_mode to the template. $variables['view_mode'] = $variables['elements']['#view_mode']; // Add the bundle to the template. $variables['entity_type'] = _civicrm_entity_get_entity_type_from_elements($variables['elements']); } /** * Implements hook_theme_suggestions_HOOK_alter(). */ function civicrm_entity_theme_suggestions_civicrm_entity_alter(array &$suggestions, array $variables) { $view_mode = $variables['elements']['#view_mode']; $hook = $variables['theme_hook_original']; // Add a suggestion based on the entity type. if ($entity_type = _civicrm_entity_get_entity_type_from_elements($variables['elements'])) { $suggestions[] = $hook . '__' . $entity_type; // Add a suggestion based on the view mode. $suggestions[] = $hook . '__' . $entity_type . '__' . $view_mode; } } /** * Helper to find the entity type from $variables['elements']. */ function _civicrm_entity_get_entity_type_from_elements($elements) { if (isset($elements['#entity_type'])) { return $elements['#entity_type']; } // Find the CivicrmEntity from elements if #entity_type is not set. foreach ($elements as $element) { if ($element instanceof CivicrmEntity) { /** @var \Drupal\civicrm_entity\Entity\CivicrmEntity $element */ return $element->getEntityTypeId(); } } return NULL; } /** * For stashing deleted entities until we need them later. * * @todo Convert hooks to a service and keep this in a member variable * * @param string $objectName * The CiviCRM entity type. * @param int $id * The id. * @param \Drupal\Core\Entity\EntityInterface|null|string $entity * The entity. * * @return void|\Drupal\Core\Entity\EntityInterface * The cached entity object. */ function _civicrm_entity_stash($objectName, $id, $entity = NULL) { $cache =& drupal_static(__FUNCTION__, []); if (empty($entity)) { return $cache[$objectName][$id] ?? NULL; } elseif ($entity === 'clear') { unset($cache[$objectName][$id]); } else { $cache[$objectName][$id] = $entity; } } /** * Implements hook_civicrm_pre(). */ function civicrm_entity_civicrm_pre($op, $objectName, $id, &$params) { if (\Drupal::config('civicrm_entity.settings')->get('disable_hooks')) { return; } $operations = ['create', 'edit', 'delete', 'restore']; if (!in_array($op, $operations)) { return; } $entityType = SupportedEntities::getEntityType($objectName); // Check valid entity type. if (!$entityType) { return; } /** @var \Drupal\civicrm_entity\CiviEntityStorage $storage */ $storage = \Drupal::entityTypeManager()->getStorage($entityType); if ($op == 'create') { /** @var \Drupal\civicrm_entity\Entity\CivicrmEntity $entity */ $entity = $storage->create($params); } elseif (empty($id)) { // Sometimes 'delete' is called with an $id of NULL, but we can't really do // anything with that in this context, so return. return; } else { // Special handling for EntityTag objects. if ($objectName == 'EntityTag') { if (isset($params['entity_id']) && isset($params['entity_table'])) { $id = $storage->getEntityTagEntityId($params['entity_id'], $params['entity_table']); } else { $id = $storage->getEntityTagEntityId($params[0][0], $params[1]); } } /** @var \Drupal\civicrm_entity\Entity\CivicrmEntity $entity */ $entity = $storage->load($id); } if (!$entity) { return; } if ($entity->id()) { $entity->original = $storage->loadUnchanged($entity->id()); } switch ($op) { case 'create': $storage->civiPreSave($entity); break; case 'delete': $storage->civiPreDelete($entity); _civicrm_entity_stash($objectName, $id, $entity); break; case 'restore': $storage->civiPreSave($entity); break; case 'edit': $storage->civiPreSave($entity); break; } } /** * Implements hook_civicrm_post(). */ function civicrm_entity_civicrm_post($op, $objectName, $objectId, &$objectRef) { if (\Drupal::config('civicrm_entity.settings')->get('disable_hooks')) { return; } $operations = ['create', 'edit', 'delete', 'restore']; if (!in_array($op, $operations)) { return; } $entityType = SupportedEntities::getEntityType($objectName); // Check valid entity type. if (!$entityType) { return; } /** @var \Drupal\civicrm_entity\CiviEntityStorage $storage */ $storage = \Drupal::entityTypeManager()->getStorage($entityType); // Fix because $objectId is not set for participant payments, possibly other // entity types. if (!$objectId) { // If we cannot determine the id, bail. if (empty($objectRef->id)) { return; } $objectId = $objectRef->id; } if ($op == 'delete') { /** @var \Drupal\civicrm_entity\Entity\CivicrmEntity $entity */ $entity = _civicrm_entity_stash($objectName, $objectId); } else { // Special handling for EntityTag objects. if ($entityType == 'civicrm_entity_tag' && is_array($objectRef)) { foreach ($objectRef[0] as $entityTag) { $object = new CRM_Core_BAO_EntityTag(); $object->entity_id = $entityTag; $object->entity_table = 'civicrm_contact'; $object->tag_id = $objectId; if ($object->find(TRUE)) { /** @var \Drupal\civicrm_entity\Entity\CivicrmEntity $entity */ $entity = $storage->load($object->id); $entity->original = $storage->loadUnchanged($entity->id()); _civicrm_entity_post_invoke($op, $storage, $entity); } } return; } /** @var \Drupal\civicrm_entity\Entity\CivicrmEntity $entity */ $entity = $storage->load($objectId); if ($entity) { $entity->original = $storage->loadUnchanged($entity->id()); } } if ($entity) { _civicrm_entity_post_invoke($op, $storage, $entity); } _civicrm_entity_stash($objectName, $objectId, 'clear'); } /** * Invokes the post save hooks for a CiviCRM entity. * * @param string $op * The operation being performed. * @param \Drupal\civicrm_entity\CiviEntityStorage $storage * The entity storage. * @param \Drupal\Core\Entity\EntityInterface $entity * The entity. */ function _civicrm_entity_post_invoke($op, CiviEntityStorage $storage, EntityInterface $entity) { switch ($op) { case 'create': $storage->civiPostSave($entity, FALSE); break; case 'delete': $storage->civiPostDelete($entity); break; case 'restore': $storage->civiPostSave($entity, TRUE); break; case 'edit': $storage->civiPostSave($entity, TRUE); break; } } /** * Implements hook_views_query_alter(). */ function civicrm_entity_views_query_alter(ViewExecutable $view, QueryPluginBase $query) { // Provide fully qualified table name in all Views queries. // If CiviCRM tables in a separate database. $civicrm_connection_name = drupal_valid_test_ua() ? 'civicrm_test' : 'civicrm'; $civicrm_database_info = Database::getConnectionInfo($civicrm_connection_name); if (isset($civicrm_database_info['default']) && method_exists($query, "getTableQueue")) { $civicrm_connection = Database::getConnection('default', $civicrm_connection_name); $table_queue =& $query->getTableQueue(); foreach ($table_queue as $alias => &$table_info) { if (!empty($table_info['table']) && ((strpos($table_info['table'], 'civicrm_') === 0 && strpos($table_info['table'], '.') === FALSE && strpos($table_info['table'], '__') === FALSE) || strpos($table_info['table'], 'civicrm_value_') === 0)) { $table_info['table'] = $civicrm_connection->getFullQualifiedTableName($table_info['table']); } if (!empty($table_info['join']->table) && ((strpos($table_info['join']->table, 'civicrm_') === 0 && strpos($table_info['join']->table, '.') === FALSE && strpos($table_info['join']->table, '__') === FALSE) || strpos($table_info['join']->table, 'civicrm_value_') === 0)) { $table_info['join']->table = $civicrm_connection->getFullQualifiedTableName($table_info['join']->table); } } } \Drupal::service('civicrm')->initialize(); $multilingual = \CRM_Core_I18n::isMultilingual(); if ($multilingual) { // @codingStandardsIgnoreStart global $dbLocale; // @codingStandardsIgnoreEnd $columns = CRM_Core_I18n_SchemaStructure::columns(); $affectedColumns = []; foreach ($columns as $table => $hash) { foreach (array_keys($hash) as $column) { $affectedColumns[] = "{$table}.{$column}"; } } $class = get_class($query); if ($class == 'Drupal\search_api\Plugin\views\query\SearchApiQuery' && method_exists($query, "getWhere")) { $where = $query->getWhere(); } elseif (isset($query->where)) { $where = $query->where; } if (!empty($where)) { foreach ($where as &$condition_group) { foreach ($condition_group['conditions'] as &$condition) { if (!is_object($condition['field'])) { foreach ($affectedColumns as $aff_column) { if (strpos($aff_column, $condition['field']) !== FALSE) { $condition['field'] = str_replace($aff_column, $aff_column . $dbLocale, $condition['field']); } } } } } } if (!empty($query->fields)) { foreach ($query->fields as &$field) { if (array_key_exists($field['table'], $columns) && array_key_exists($field['field'], $columns[$field['table']])) { $field['field'] .= $dbLocale; } } } } } /** * Implements hook_theme_registry_alter(). */ function civicrm_entity_theme_registry_alter(&$theme_registry) { $theme_registry['civicrm_entity']['preprocess functions'][] = 'field_group_build_entity_groups'; } /** * Implements hook_rebuild(). * * This resets the field storage and entity type definitions for civicrm_entity * according to the active definitions to avoid mismatches since the definitions * are not necessary to be updated. */ function civicrm_entity_rebuild() { /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_repository */ $entity_last_installed_repository = \Drupal::service('entity.last_installed_schema.repository'); /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager */ $entity_field_manager = \Drupal::service('entity_field.manager'); /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ $entity_type_manager = \Drupal::service('entity_type.manager'); $supported_entities = SupportedEntities::getInfo(); foreach (array_keys($supported_entities) as $entity_type_id) { // Reset field storage definitions. $field_storage_definitions = $entity_field_manager->getFieldStorageDefinitions($entity_type_id); $entity_last_installed_repository->setLastInstalledFieldStorageDefinitions($entity_type_id, $field_storage_definitions); // Reset entity type definition. $definition = $entity_type_manager->getDefinition($entity_type_id); $entity_last_installed_repository->setLastInstalledDefinition($definition); } } /** * Implements hook_rules_action_info_alter(). */ function civicrm_entity_rules_action_info_alter(&$rules_actions) { $definitions = \Drupal::service('plugin.manager.typed_data_filter')->getDefinitions(); $filters = ""; foreach ($definitions as $key) { if ($key['provider'] == 'civicrm_entity') { $filters .= ($filters == '' ? '' : ', ') . $key['id']; } } if (array_key_exists('format', $rules_actions['civicrm_entity_user_create']['context_definitions'])) { // Drupal 9 use 'context_definitions' instead of 'context'. $rules_actions['civicrm_entity_user_create']['context_definitions']['format']->setDescription(t('Format of the username. Use <a href="@url">Twig style</a> tokens for using the available data.<br>Civicrm Entity filter available : @filters.', [ '@url' => 'https://www.drupal.org/docs/8/modules/typed-data-api-enhancements/typeddata-tokens', '@filters' => $filters, ])); } else { $rules_actions['civicrm_entity_user_create']['context']['format']->setDescription(t('Format of the username. Use <a href="@url">Twig style</a> tokens for using the available data.<br>Civicrm Entity filter available : @filters.', [ '@url' => 'https://www.drupal.org/docs/8/modules/typed-data-api-enhancements/typeddata-tokens', '@filters' => $filters, ])); } } /** * Implements hook_search_api_datasource_info_alter(). */ function civicrm_entity_search_api_datasource_info_alter(array &$infos) { foreach ($infos as $entity_type => &$info) { if (strpos($entity_type, 'entity:civicrm_') !== FALSE) { unset($info['deriver']); $info['class'] = DatasourceCivicrmEntity::class; } } } /** * Implements hook_civicrm_merge(). */ function civicrm_entity_civicrm_merge($mode, &$sqls, $mainId = NULL, $otherId = NULL, $tables = NULL) { if ($mode == 'sqls' && !empty($mainId) && !empty($otherId)) { // Get List if civicrm contact entity reference field. $entityRefFields = \Drupal::entityTypeManager()->getStorage('field_storage_config') ->loadByProperties([ 'type' => 'entity_reference', 'settings' => ['target_type' => 'civicrm_contact'], ]); // Iterate fields and prepare the array. foreach ($entityRefFields as $entityRefField) { // Get Field name. $fieldName = $entityRefField->getName(); // Get Type, Node etc.. $entityRefType = $entityRefField->getTargetEntityTypeId(); $options[$entityRefType][] = $fieldName; } foreach ($options as $type => $fields) { foreach ($fields as $field) { try { // $otherId is duplicate contact ID $ids = \Drupal::entityQuery($type) ->condition($field, $otherId, '=') ->accessCheck(FALSE) ->execute(); if (!empty($ids)) { $entityRecords = Drupal::entityTypeManager()->getStorage($type) ->loadMultiple($ids); foreach ($entityRecords as $entityRecord) { // Update new contact. // Target Contact. try { $entityRecord->set($field, $mainId); $entityRecord->save(); } catch (\Exception $e) { \Drupal::logger('civicrm_entity')->error($e->getMessage()); } } } } catch (\Exception $e) { \Drupal::logger('civicrm_entity')->error($e->getMessage()); } } } } } /** * Implements hook_query_TAG_alter(). */ function civicrm_entity_query_pathauto_bulk_update_alter(AlterableInterface $query) { $tables = &$query->getTables(); if (strpos($tables['base_table']['table'], 'civicrm_') !== FALSE) { $civicrm_connection_name = drupal_valid_test_ua() ? 'civicrm_test' : 'civicrm'; $civicrm_database_info = Database::getConnectionInfo($civicrm_connection_name); if (isset($civicrm_database_info['default'])) { $connection = Database::getConnection('default', $civicrm_connection_name); $tables['base_table']['table'] = $connection->getFullQualifiedTableName($tables['base_table']['table']); } } } /** * Implements hook_query_TAG_alter(). */ function civicrm_entity_query_pathauto_bulk_delete_alter(AlterableInterface $query) { $tables = &$query->getTables(); if (strpos($tables['base_table']['table'], 'civicrm_') !== FALSE) { $civicrm_connection_name = drupal_valid_test_ua() ? 'civicrm_test' : 'civicrm'; $civicrm_database_info = Database::getConnectionInfo($civicrm_connection_name); if (isset($civicrm_database_info['default'])) { $connection = Database::getConnection('default', $civicrm_connection_name); $tables['base_table']['table'] = $connection->getFullQualifiedTableName($tables['base_table']['table']); } } }