sites_group_overrides-1.x-dev/src/SitesGroupOverridesService.php

src/SitesGroupOverridesService.php
<?php

declare(strict_types=1);

namespace Drupal\sites_group_overrides;

use Drupal\field\FieldConfigInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\sites_group\SitesGroupServiceInterface;
use Drupal\group\Entity\GroupRelationshipInterface;
use Drupal\group\Entity\Storage\GroupRelationshipStorageInterface;
use Drupal\sites_group_overrides\Event\SyncFieldToEntity;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
use Drupal\sites\SiteInterface;

/**
 * The sites_group_override service.
 */
class SitesGroupOverridesService implements SitesGroupOverridesServiceInterface {

  /**
   * Constructs a SitesGroupService object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager.
   * @param \Drupal\sites_group\SitesGroupServiceInterface $sitesGroupService
   *   The sites_group service.
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
   *   The event dispatcher.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
   *   The entity field manager.
   */
  public function __construct(
    protected readonly EntityTypeManagerInterface $entityTypeManager,
    protected readonly SitesGroupServiceInterface $sitesGroupService,
    protected readonly EventDispatcherInterface $eventDispatcher,
    protected readonly EntityFieldManagerInterface $entityFieldManager,
  ) {}


  public function getBlacklist($entity) {
    return [
      'uid',
      'created',
      'updated',
      "{$entity->getEntityTypeId()}__layout_builder__layout",
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function syncFieldsToEntity(GroupRelationshipInterface $relationship, ContentEntityInterface $entity): ContentEntityInterface {
    foreach ($this->getSynchronizableFields($relationship, $entity) as $field_name => $field) {
      if ($entity->hasField($field_name) && !$field->isEmpty() && empty($entity->{$field_name}->overriden)) {
        // Maybe one can move this to an event subscriber too.
        $entity->set($field_name, $field->getValue());
        $event = new SyncFieldToEntity($entity, $field_name, $field);
        $this->eventDispatcher->dispatch($event, SyncFieldToEntity::EVENT_NAME);
        $entity->{$field_name}->overriden = TRUE;
      }
    }

    return $entity->addCacheableDependency($relationship);
  }

  /**
   * {@inheritdoc}
   *
   * @todo use static cache
   */
  public function getSynchronizableFields(GroupRelationshipInterface $relationship, ContentEntityInterface $entity, bool $reuse_source_value = TRUE): array {
    $fields = [];

    foreach ($entity->getFields(FALSE) as $field_name => $field) {
      if (!in_array($field_name, $this->getBlacklist($relationship))) {
        $field_definition = $entity->get($field_name)->getFieldDefinition();
        $override_settings = $this->getSettings($field_definition, $entity, $relationship);

        if (empty($override_settings['use_overrides'])) {
          continue;
        }

        if ($relationship->hasField($override_settings['target_field_name'])) {
          $fields[$field_name] = $relationship->get($override_settings['target_field_name']);
          if ($reuse_source_value && $relationship->get($override_settings['target_field_name'])->isEmpty()) {
            // Overridable but not overidden -> use target value.
            $fields[$field_name]->setValue($entity->get($field_name)->getValue());
          }
        }
      }
    }

    return $fields;
  }

  /**
   * {@inheritdoc}
   */
  public function getSourceBundleEntityTypes(): array {
    $entity_types = [];
    $group_types = $this->entityTypeManager->getStorage('group_type')->loadMultiple();
    foreach ($group_types as $group_type) {
      foreach ($group_type->getInstalledPlugins() as $plugin) {
        $definition = $plugin->getPluginDefinition();
        if (!$definition->get('entity_type_id')) {
          continue;
        }

        if ($bundle_entity_type_id = $this->entityTypeManager->getDefinition($definition->get('entity_type_id'))->get('bundle_entity_type')) {
          $bundle_entity_type = $this->entityTypeManager->getDefinition($bundle_entity_type_id);
          $entity_types[$bundle_entity_type->get('id')] = $bundle_entity_type;
        }
      }
    }

    return $entity_types;
  }

  /**
   * Get sites_group_overrides settings for the specified field.
   *
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
   *   The field definition to get the settings for.
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The (target) entity.
   * @param \Drupal\group\Entity\GroupRelationshipInterface; $relationship
   *   The relationship entity.
   * @return array
   *   The sites_group_overrides settings
   */
  private function getSettings(FieldDefinitionInterface $field_definition, ContentEntityInterface $entity, GroupRelationshipInterface $relationship): array {
    $bundle = $relationship->getRelationshipType()->id();
    if ($field_definition instanceof FieldConfigInterface) {
      return (array) $field_definition->getThirdPartySetting('sites_group_overrides', $bundle);
    }
    if ($field_definition instanceof FieldDefinitionInterface) {
      return (array) $field_definition->getConfig($entity->bundle())->getThirdPartySetting('sites_group_overrides', $bundle);
    }

    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getTargetFieldName(GroupRelationshipInterface $relationship, string $field_name): ?string {
    // Determine field-definition w/o calling ->getEntity() because it messes up the relationship.
    $definition = $relationship->getPlugin()->getPluginDefinition();
    $bundle = $entity_type_id = $definition->get('entity_type_id');
    if ($definition->get('entity_bundle')) {
      $bundle = $definition->get('entity_bundle');
    }

    if ($field_definition = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $bundle)[$field_name] ?? NULL) {
      $settings = $field_definition->getThirdPartySetting('sites_group_overrides', $relationship->bundle(), []);
    }

    if (empty($settings['use_overrides']) || empty($settings['target_field_name'])) {
      return NULL;
    }

    return $relationship->hasField($settings['target_field_name']) ? $settings['target_field_name'] : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function entityIsOveridable(ContentEntityInterface $entity): bool {
    if ($relationship = $this->getRelationship($entity)) {
      return count($this->getSynchronizableFields($relationship, $entity)) > 0;
    }

    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function getRelationship(ContentEntityInterface $entity): ?GroupRelationshipInterface {
    return $this->sitesGroupService->getRelationship($entity);
  }

  /**
   * {@inheritdoc}
   */
  public function entityIsOverridden(ContentEntityInterface $entity, GroupRelationshipInterface $relationship): bool {
    // Reload unchanged - overrides might already be in the entity cache.
    $langcode = $relationship->language()->getId();
    /** @var \Drupal\group\Entity\GroupRelationshipInterface $relationship */
    $relationship = $this->entityTypeManager->getStorage('group_relationship')->loadUnchanged($relationship->id());

    try {
     $relationship = $relationship->getTranslation($langcode);
    }
    catch (\InvalidArgumentException $e) {
      return FALSE;
    }
    foreach ($this->getSynchronizableFields($relationship, $entity, FALSE) as $field_name => $field) {
      if (!$relationship->get($this->getTargetFieldName($relationship, $field_name))->isEmpty()) {
        return TRUE;
      }
    }

    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function getRelationshipsWithOverrides(ContentEntityInterface $entity): array {
    $relationships = [];

    /** @var GroupRelationshipStorageInterface $relationship_storage */
    $relationship_storage = $this->entityTypeManager->getStorage('group_relationship');
    foreach ($this->sitesGroupService->getGroups($entity) as $group) {
      $relationship_candidates = $relationship_storage->loadByEntityAndGroup($entity, $group);

      foreach ($relationship_candidates as $relationship_candidate) {
        try {
          $relationship_candidate = $relationship_candidate->getTranslation($entity->language()->getId());
        }
        catch (\InvalidArgumentException $e) {
          continue;
        }
        if ($this->entityIsOverridden($entity, $relationship_candidate)) {
          $relationships[] = $relationship_candidate;
        }
      }
    }

    return $relationships;
  }

  /**
   * {@inheritdoc}
   */
  public function revertOverride(GroupRelationshipInterface $relationship) {
    $group = $relationship->getGroup();
    $plugin_id = $relationship->getPluginId();
    $entity = $relationship->getEntity();

    // Delete the relationship.
    $relationship->delete();

    // Create a new relationship.
    $group->addRelationship($entity, $plugin_id);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc