rdf_sync-1.x-dev/rdf_sync.module
rdf_sync.module
<?php
/**
* @file
* Hook implementations for RDF Sync module.
*/
declare(strict_types=1);
use Drupal\Core\Config\Entity\ThirdPartySettingsInterface;
use Drupal\Core\Entity\BundleEntityFormBase;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\field_ui\Form\FieldConfigEditForm;
use Drupal\rdf_sync\BundleFieldDefinition;
use Drupal\rdf_sync\Form\Alter\BundleEntityFormAlter;
use Drupal\rdf_sync\Form\Alter\FieldConfigFormAlter;
use Drupal\rdf_sync\Model\ColumnMapping;
use Drupal\rdf_sync\Model\SyncMethod;
use Drupal\rdf_sync\RdfSyncUriFieldItemList;
/**
* Implements hook_entity_bundle_info_alter().
*/
function rdf_sync_entity_bundle_info_alter(array &$bundles): void {
$entityTypeManager = \Drupal::entityTypeManager();
$entityFieldManager = \Drupal::getContainer()->get('entity_field.manager');
foreach ($entityTypeManager->getDefinitions() as $entityTypeId => $entityType) {
if (!$entityType->entityClassImplements(ContentEntityInterface::class) || !($bundleEntityTypeId = $entityType->getBundleEntityType())) {
// Filter out config entities or entities without bundle as config entity.
continue;
}
$bundleStorage = $entityTypeManager->getStorage($bundleEntityTypeId);
/** @var \Drupal\Core\Config\Entity\ConfigEntityInterface&\Drupal\Core\Config\Entity\ThirdPartySettingsInterface $bundle */
foreach ($bundleStorage->loadMultiple() as $bundleId => $bundle) {
if ($rdfSyncSettings = $bundle->getThirdPartySettings('rdf_sync')) {
if (empty($rdfSyncSettings['type'])) {
// Malformed mapping.
throw new \Exception("Mapping $entityTypeId:$bundleId is missing the 'type' value");
}
// Add bundle level mappings.
$rdfSyncSettings += ['fields' => []];
array_walk($rdfSyncSettings['fields'], 'rdf_sync_check_column_mappings', [$entityTypeId, $bundleId]);
$bundles[$entityTypeId][$bundleId]['rdf_sync'] = $rdfSyncSettings;
// Add configurable fields mappings.
foreach ($entityFieldManager->getFieldDefinitions($entityTypeId, $bundleId) as $fieldName => $fieldDefinition) {
if (!$fieldDefinition instanceof ThirdPartySettingsInterface) {
continue;
}
$columns = $fieldDefinition->getThirdPartySettings('rdf_sync');
rdf_sync_check_column_mappings($columns, $fieldName, [$entityTypeId, $bundleId]);
foreach ($columns as $columnName => $mapping) {
$bundles[$entityTypeId][$bundleId]['rdf_sync']['fields'][$fieldName][$columnName] = $mapping;
}
}
}
}
}
}
/**
* Checks the mapped columns from a field.
*
* @param array $columns
* The mapped columns of a given field.
* @param string $fieldName
* The field name.
* @param array $entityTypeAndBundle
* A tuple:
* 0: the entity type ID,
* 1: the bundle.
*
* @throws \Exception
* Various exceptions when the mappings have errors.
*/
function rdf_sync_check_column_mappings(array $columns, string $fieldName, array $entityTypeAndBundle): void {
[$entityTypeId, $bundleId] = $entityTypeAndBundle;
foreach ($columns as $columnName => $mapping) {
if (empty($mapping['predicate'])) {
throw new \Exception("Mapping of $entityTypeId:$bundleId:$fieldName:$columnName is missing the 'predicate' value");
}
if (!array_key_exists('type', $mapping)) {
throw new \Exception("Mapping of $entityTypeId:$bundleId:$fieldName:$columnName is missing the 'type' value");
}
if ($mapping['type'] !== NULL && !in_array($mapping['type'], ColumnMapping::ALLOWED_TYPES, TRUE)) {
throw new \Exception("The 'type' key of $entityTypeId:$bundleId:$fieldName:$columnName mapping should be NULL or one of '" . implode("', '", ColumnMapping::ALLOWED_TYPES) . "'");
}
// @todo The 'type' can be NULL only on translatable string fields. Find a
// way to check this early. Getting here the field definition to check
// whether is translatable will call rdf_sync_entity_bundle_field_info()
// which will call RdfSyncMapper::isMappedBundle() but the bundle info is
// not yet prepared (we're in the middle of the process).
}
}
/**
* Implements hook_entity_bundle_field_info().
*/
function rdf_sync_entity_bundle_field_info(EntityTypeInterface $entityType, string $bundle, array $baseFieldDefinitions): array {
$fields = [];
$mapper = \Drupal::getContainer()->get('rdf_sync.mapper');
if ($bundle && $mapper->isMappedBundle($entityType->id(), $bundle)) {
$fieldName = $mapper->getRdfUriFieldName($entityType->id(), $bundle);
$fields[$fieldName] = BundleFieldDefinition::create('uri')
->setName($fieldName)
->setTargetEntityTypeId($entityType->id())
->setTargetBundle($bundle)
->setLabel(t('URI'))
->setRequired(TRUE)
->setComputed(TRUE)
->setCustomStorage(TRUE)
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE)
->setRevisionable(FALSE)
->setClass(RdfSyncUriFieldItemList::class);
}
return $fields;
}
/**
* Implements hook_form_alter().
*/
function rdf_sync_form_alter(array &$form, FormStateInterface $form_state): void {
$formObject = $form_state->getFormObject();
if ($formObject instanceof BundleEntityFormBase) {
$formAlter = \Drupal::classResolver(BundleEntityFormAlter::class);
}
elseif ($formObject instanceof FieldConfigEditForm) {
$formAlter = \Drupal::classResolver(FieldConfigFormAlter::class);
}
/** @var \Drupal\rdf_sync\Form\Alter\FormAlterInterface|NULL $formAlter */
if (isset($formAlter)) {
$formAlter->alter($form, $form_state);
}
}
/**
* Implements hook_entity_insert().
*/
function rdf_sync_entity_insert(EntityInterface $entity): void {
$mapper = \Drupal::getContainer()->get('rdf_sync.mapper');
if ($entity instanceof ContentEntityInterface && $mapper->isMappedEntity($entity)) {
\Drupal::getContainer()->get('rdf_sync.synchronizer')->synchronize(SyncMethod::INSERT, [$entity]);
}
}
/**
* Implements hook_entity_update().
*/
function rdf_sync_entity_update(EntityInterface $entity): void {
$mapper = \Drupal::getContainer()->get('rdf_sync.mapper');
if ($entity instanceof ContentEntityInterface && $mapper->isMappedEntity($entity)) {
\Drupal::getContainer()->get('rdf_sync.synchronizer')->synchronize(SyncMethod::UPDATE, [$entity]);
}
}
/**
* Implements hook_entity_delete().
*/
function rdf_sync_entity_delete(EntityInterface $entity): void {
$mapper = \Drupal::getContainer()->get('rdf_sync.mapper');
if ($entity instanceof ContentEntityInterface && $mapper->isMappedEntity($entity)) {
// Compute the URI so that is cached in the field item list to be available
// in destruction phase.
$fieldName = \Drupal::getContainer()->get('rdf_sync.mapper')->getRdfUriFieldName(entity: $entity);
if ($entity->get($fieldName)->value) {
\Drupal::getContainer()->get('rdf_sync.synchronizer')->synchronize(SyncMethod::DELETE, [$entity]);
}
\Drupal::database()->delete('rdf_sync_uri')
->condition('entity_type', $entity->getEntityTypeId())
->condition('entity_id', $entity->id())
->execute();
}
}
