clean install

This commit is contained in:
2024-12-10 15:08:16 +01:00
commit e14eb2d8fd
31193 changed files with 3555714 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
<?php
namespace Drupal\entity_reference_integrity;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
/**
* Create a map of reference fields.
*/
class DependencyFieldMapGenerator implements DependencyFieldMapGeneratorInterface {
/**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
private $entityTypeManager;
/**
* The field type plugin ID.
*
* @var string
*/
protected $fieldType;
/**
* The settings key for the target entity type ID.
*
* @var string
*/
protected $targetEntitySettingsKey;
/**
* Construct a ReferenceFieldMapGenerator.
*/
public function __construct(EntityFieldManagerInterface $entityFieldManager, EntityTypeManagerInterface $entityTypeManager, $fieldType, $targetEntitySettingsKey) {
$this->entityFieldManager = $entityFieldManager;
$this->entityTypeManager = $entityTypeManager;
$this->fieldType = $fieldType;
$this->targetEntitySettingsKey = $targetEntitySettingsKey;
}
/**
* {@inheritdoc}
*/
public function getReferentialFieldMap() {
$referential_field_map = [];
foreach ($this->entityFieldManager->getFieldMapByFieldType($this->fieldType) as $source_entity_type_id => $fields) {
$source_entity_storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($source_entity_type_id);
$source_entity_type = $this->entityTypeManager->getDefinition($source_entity_type_id);
foreach ($fields as $field_name => $field_data) {
$field_storage_definition = !empty($source_entity_storage_definitions[$field_name]) ? $source_entity_storage_definitions[$field_name] : FALSE;
// Some fields like computed fields do not show up in the return value
// of getFieldStorageDefinitions.
if (!$field_storage_definition) {
continue;
}
// Fields with custom storage like term parents can't be used with
// entity query.
if ($field_storage_definition->hasCustomStorage()) {
continue;
}
// Don't query against revision metadata fields.
if (in_array($field_name, $source_entity_type->getRevisionMetadataKeys())) {
continue;
}
$target_entity_type_id = $source_entity_storage_definitions[$field_name]->getSetting($this->targetEntitySettingsKey);
$referential_field_map[$target_entity_type_id][$source_entity_type_id][] = $field_name;
}
}
return $referential_field_map;
}
/**
* {@inheritdoc}
*/
public function getReferencingFields($entity_type_id) {
$map = $this->getReferentialFieldMap();
return isset($map[$entity_type_id]) ? $map[$entity_type_id] : [];
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Drupal\entity_reference_integrity;
/**
* An interface for generating field maps.
*/
interface DependencyFieldMapGeneratorInterface {
/**
* A field map keyed by the entity type being targeted by reference fields.
*
* The referential field map is in the format of:
*
* entity_type_id_being_referenced:
* source_entity_type_id:
* - referencing_field_a
* - referencing_field_b
*
* @return array
* A field map.
*/
public function getReferentialFieldMap();
/**
* Get the segment of the field map for a specific entity type ID.
*
* @param string $entity_type_id
* An entity type ID.
*
* @return array
* A segment of the field map.
*/
public function getReferencingFields($entity_type_id);
}

View File

@@ -0,0 +1,63 @@
<?php
namespace Drupal\entity_reference_integrity;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
/**
* Calculate entity dependencies based on entity reference fields.
*
* @deprecated Use the entity handler instead.
*/
class EntityReferenceDependencyManager implements EntityReferenceDependencyManagerInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Create an EntityReferenceDependencyManager.
*/
public function __construct(EntityTypeManagerInterface $entityTypeManager) {
$this->entityTypeManager = $entityTypeManager;
}
/**
* {@inheritdoc}
*/
public function hasDependents(EntityInterface $entity) {
return $this->entityTypeManager
->getHandler($entity->getEntityTypeId(), 'entity_reference_integrity')
->hasDependents($entity);
}
/**
* {@inheritdoc}
*/
public function getDependentEntityIds(EntityInterface $entity) {
return $this->entityTypeManager
->getHandler($entity->getEntityTypeId(), 'entity_reference_integrity')
->getDependentEntityIds($entity);
}
/**
* {@inheritdoc}
*/
public function getDependentEntities(EntityInterface $entity) {
return $this->entityTypeManager
->getHandler($entity->getEntityTypeId(), 'entity_reference_integrity')
->getDependentEntities($entity);
}
/**
* {@inheritdoc}
*/
public static function getAccessDeniedReason(EntityInterface $entity, bool $translate = TRUE) {
return EntityReferenceIntegrityEntityHandler::getAccessDeniedReason($entity, $translate);
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Drupal\entity_reference_integrity;
use Drupal\Core\Entity\EntityInterface;
/**
* An interface for calculating entity dependency.
*/
interface EntityReferenceDependencyManagerInterface {
/**
* Check if an entity has dependent entties.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* An entity.
*
* @return bool
* If the entity is referenced from elsewhere.
*/
public function hasDependents(EntityInterface $entity);
/**
* List the entities that reference the given entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
*
* @return array
* Array of entity type IDs with arrays of loaded entities.
*/
public function getDependentEntities(EntityInterface $entity);
/**
* List the entity IDs that reference the given entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
*
* @return array
* Array of entity type IDs with arrays of entity IDs.
*/
public function getDependentEntityIds(EntityInterface $entity);
/**
* Build an access denied reason string.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity that has dependents.
* @param bool $translate
* Optional boolean to translate the string. Defaults to TRUE.
*
* @return string
*/
public static function getAccessDeniedReason(EntityInterface $entity, bool $translate = TRUE);
}

View File

@@ -0,0 +1,136 @@
<?php
namespace Drupal\entity_reference_integrity;
use Drupal\Core\Entity\EntityHandlerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Entity reference integrity entity handler.
*/
class EntityReferenceIntegrityEntityHandler implements EntityHandlerInterface, EntityReferenceDependencyManagerInterface {
/**
* A referential field map.
*
* @var \Drupal\entity_reference_integrity\DependencyFieldMapGeneratorInterface
*/
protected $fieldMap;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Create an EntityReferenceDependencyManager.
*/
public function __construct(DependencyFieldMapGeneratorInterface $fieldMap, EntityTypeManagerInterface $entityTypeManager) {
$this->fieldMap = $fieldMap;
$this->entityTypeManager = $entityTypeManager;
}
/**
* {@inheritdoc}
*/
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static(
$container->get('entity_reference_integrity.field_map'),
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function hasDependents(EntityInterface $entity) {
$referencing_fields = $this->fieldMap->getReferencingFields($entity->getEntityTypeId());
foreach ($referencing_fields as $source_entity_type_id => $source_fields) {
// Select a count of all entities of type $source_entity_type_id which
// have any one of their entity reference fields pointing to the given
// entity.
$number_of_referencing_entities = $this->referentialEntityQuery($source_entity_type_id, $source_fields, $entity->id())
->count()
->execute();
// Stop immediately if we find any foreign entity which references our own
// entity.
if ($number_of_referencing_entities > 0) {
return TRUE;
}
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function getDependentEntityIds(EntityInterface $entity) {
$referencing_entities = [];
$referencing_fields = $this->fieldMap->getReferencingFields($entity->getEntityTypeId());
foreach ($referencing_fields as $source_entity_type_id => $source_fields) {
$entity_ids = array_values($this->referentialEntityQuery($source_entity_type_id, $source_fields, $entity->id())->execute());
if (!empty($entity_ids)) {
$referencing_entities[$source_entity_type_id] = $entity_ids;
}
}
return $referencing_entities;
}
/**
* {@inheritdoc}
*/
public function getDependentEntities(EntityInterface $entity) {
$entities = $this->getDependentEntityIds($entity);
$loaded_entities = [];
foreach ($entities as $entity_type_id => $ids) {
$loaded_entities[$entity_type_id] = array_values($this->entityTypeManager->getStorage($entity_type_id)->loadMultiple($ids));
}
return $loaded_entities;
}
/**
* Start an entity query for entities matching set conditions.
*
* Query for all entities of the specified type which have any fields in the
* source field list that match the given target ID.
*
* @param string $entity_type
* The entityt type.
* @param array $source_fields
* An array of source fields.
* @param string|int $target_id
* The target ID to search for.
*
* @return \Drupal\Core\Entity\Query\QueryInterface
* A query object.
*/
protected function referentialEntityQuery($entity_type, array $source_fields, $target_id) {
$query = $this->entityTypeManager->getStorage($entity_type)->getQuery()->accessCheck(TRUE);
$or_group = $query->orConditionGroup();
foreach ($source_fields as $source_field) {
$or_group->condition($source_field, $target_id, '=');
}
$query->condition($or_group);
return $query;
}
/**
* {@inheritdoc}
*/
public static function getAccessDeniedReason($entity, $translate = TRUE) {
$reason = new TranslatableMarkup('Can not delete the @entity_type_label %entity_label as it is being referenced by another entity.', [
'@entity_type_label' => $entity->getEntityType()->getLabel(),
'%entity_label' => $entity->label(),
]);
return $translate ? $reason->render() : $reason->getUntranslatedString();
}
}