You are here

dynamic_entity_reference.module in Dynamic Entity Reference 8.2

Same filename and directory in other branches
  1. 8 dynamic_entity_reference.module
  2. 7 dynamic_entity_reference.module

Contains main module functionality.

File

dynamic_entity_reference.module
View source
<?php

/**
 * @file
 * Contains main module functionality.
 */
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceItem;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\FieldConfigInterface;

/**
 * Implements hook_entity_bundle_delete().
 *
 * We are duplicating the work done by
 * \Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceItem::onDependencyRemoval()
 * because we need to take into account bundles that are not provided by a
 * config entity type so they are not part of the config dependencies.
 */
function dynamic_entity_reference_entity_bundle_delete($entity_type_id, $bundle) {

  // Gather a list of all entity reference fields.
  $map = Drupal::service('entity_field.manager')
    ->getFieldMapByFieldType('dynamic_entity_reference');
  $ids = [];
  foreach ($map as $type => $info) {
    foreach ($info as $name => $data) {
      foreach ($data['bundles'] as $bundle_name) {
        $ids[] = "{$type}.{$bundle_name}.{$name}";
      }
    }
  }

  // Update the 'target_bundles' handler setting if needed.
  foreach (FieldConfig::loadMultiple($ids) as $field_config) {
    $settings = $field_config
      ->getSettings();
    $target_types = DynamicEntityReferenceItem::getTargetTypes($settings);
    if (in_array($entity_type_id, $target_types, TRUE) && isset($settings[$entity_type_id]['handler_settings'])) {
      $handler_settings = $settings[$entity_type_id]['handler_settings'];
      if (isset($handler_settings['target_bundles'][$bundle])) {
        unset($handler_settings['target_bundles'][$bundle]);
        $settings[$entity_type_id]['handler_settings'] = $handler_settings;
        $field_config
          ->setSettings($settings);
        $field_config
          ->save();

        // In case we deleted the only target bundle allowed by the field we
        // have to log a critical message because the field will not function
        // correctly anymore.
        if ($handler_settings['target_bundles'] === []) {
          \Drupal::logger('dynamic_entity_reference')
            ->critical('The %target_bundle bundle (entity type: %target_entity_type) was deleted. As a result, the %field_name dynamic entity reference field (entity_type: %entity_type, bundle: %bundle) no longer has any valid bundle it can reference. The field is not working correctly anymore and has to be adjusted.', [
            '%target_bundle' => $bundle,
            '%target_entity_type' => $entity_type_id,
            '%field_name' => $field_config
              ->getName(),
            '%entity_type' => $field_config
              ->getTargetEntityTypeId(),
            '%bundle' => $field_config
              ->getTargetBundle(),
          ]);
        }
      }
    }
  }
}

/**
 * Implements hook_ENTITY_TYPE_presave().
 *
 * @todo Clean this up once field_field_config_save is more accommodating.
 */
function dynamic_entity_reference_field_config_presave(FieldConfigInterface $field) {

  // Don't change anything during a configuration sync.
  if ($field
    ->isSyncing()) {
    return;
  }
  $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
  $er_item_class = EntityReferenceItem::class;
  $class = $field_type_manager
    ->getPluginClass($field
    ->getType());
  if ($class !== $er_item_class && !is_subclass_of($class, $er_item_class)) {
    return;
  }
  $der_item_class = DynamicEntityReferenceItem::class;
  if ($class === $der_item_class || is_subclass_of($class, $der_item_class)) {

    // DER needs to be handled differently.
    return;
  }

  // Just a normal ER item, do the things field_field_config_presave() would
  // have done before we removed it in
  // dynamic_entity_reference_module_implements_alter().
  $selection_manager = \Drupal::service('plugin.manager.entity_reference_selection');
  $target_type = $field
    ->getFieldStorageDefinition()
    ->getSetting('target_type');
  list($current_handler) = explode(':', $field
    ->getSetting('handler'), 2);
  $field
    ->setSetting('handler', $selection_manager
    ->getPluginId($target_type, $current_handler));
}

/**
 * Implements hook_module_implements_alter().
 */
function dynamic_entity_reference_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'field_config_presave') {

    // We have to go after field_field_config_presave().
    $group = $implementations['dynamic_entity_reference'];
    unset($implementations['dynamic_entity_reference']);

    // Remove the field implementation, we have a fallback in our hook.
    unset($implementations['field']);
    $implementations['dynamic_entity_reference'] = $group;
  }
}

/**
 * Implements hook_form_FORM_ID_alter() for 'field_ui_field_storage_add_form'.
 */
function dynamic_entity_reference_form_field_ui_field_storage_add_form_alter(array &$form) {
  $optgroup = (string) t('Dynamic Reference');

  // Move the "Dynamic entity reference" option to the end of the list and
  // rename it to "Other".
  unset($form['add']['new_storage_type']['#options'][$optgroup]['dynamic_entity_reference']);
  $form['add']['new_storage_type']['#options'][$optgroup]['dynamic_entity_reference'] = t('Other…');
}