rdf_sync-1.x-dev/src/RdfSyncMapper.php
src/RdfSyncMapper.php
<?php
declare(strict_types=1);
namespace Drupal\rdf_sync;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\rdf_sync\Model\ColumnMapping;
/**
* RDF Sync mapper service.
*/
class RdfSyncMapper implements RdfSyncMapperInterface {
public function __construct(
protected EntityTypeBundleInfoInterface $entityTypeBundleInfo,
protected EntityTypeManagerInterface $entityTypeManager,
protected Connection $database,
) {}
/**
* {@inheritdoc}
*/
public function entityTypeHasMappings(string $entityTypeId): bool {
foreach ($this->entityTypeBundleInfo->getBundleInfo($entityTypeId) as $bundleId => $bundleInfo) {
if ($this->isMappedBundle($entityTypeId, $bundleId)) {
return TRUE;
}
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function getBundleRdfType(?string $entityTypeId = NULL, ?string $bundle = NULL, ?ContentEntityInterface $entity = NULL): ?string {
$this->resolveEntityTypeAndBundle($entityTypeId, $bundle, $entity);
return $this->getBundleMapping($entityTypeId, $bundle)['type'] ?? NULL;
}
/**
* {@inheritdoc}
*/
public function isMappedBundle(string $entityTypeId, string $bundle): bool {
return (bool) $this->getBundleRdfType($entityTypeId, $bundle);
}
/**
* {@inheritdoc}
*/
public function isMappedEntity(EntityInterface $entity): bool {
return $this->isMappedBundle($entity->getEntityTypeId(), $entity->bundle());
}
/**
* {@inheritdoc}
*/
public function getMappings(?string $entityTypeId = NULL, ?string $bundle = NULL, ?ContentEntityInterface $entity = NULL): array {
$this->resolveEntityTypeAndBundle($entityTypeId, $bundle, $entity);
$mappings = [];
foreach ($this->getBundleMapping($entityTypeId, $bundle)['fields'] ?? [] as $fieldName => $columns) {
foreach ($columns as $columnName => $mapping) {
$mappings[$fieldName][$columnName] = ColumnMapping::createFromArray($mapping);
}
}
return $mappings;
}
/**
* {@inheritdoc}
*/
public function getRdfUriFieldName(?string $entityTypeId = NULL, ?string $bundle = NULL, ?ContentEntityInterface $entity = NULL): string {
$this->resolveEntityTypeAndBundle($entityTypeId, $bundle, $entity);
return $this->getBundleMapping($entityTypeId, $bundle)['uri_field_name'];
}
/**
* {@inheritdoc}
*/
public function getRdfUriPluginId(string $entityTypeId, string $bundle): ?string {
return $this->getBundleMapping($entityTypeId, $bundle)['uri_plugin'] ?? NULL;
}
/**
* {@inheritdoc}
*/
public function getNamespaces(?string $entityTypeId = NULL, ?string $bundle = NULL, ?ContentEntityInterface $entity = NULL): array {
$this->resolveEntityTypeAndBundle($entityTypeId, $bundle, $entity);
return $this->getBundleMapping($entityTypeId, $bundle)['namespaces'] ?? [];
}
/**
* {@inheritdoc}
*/
public function hasBundleMapping(ContentEntityInterface $entity): bool {
$bundleKey = $entity->getEntityType()->getKey('bundle');
$fieldMappings = $this->getMappings($entity->getEntityTypeId(), $entity->bundle());
if (!isset($fieldMappings[$bundleKey])) {
return FALSE;
}
$mainProperty = $entity->getFieldDefinition($bundleKey)->getFieldStorageDefinition()->getMainPropertyName();
return isset($fieldMappings[$bundleKey][$mainProperty]);
}
/**
* {@inheritdoc}
*/
public function getEntityByUri(string $uri): ?ContentEntityInterface {
$row = $this->database->select('rdf_sync_uri')
->fields('rdf_sync_uri', ['entity_type', 'entity_id'])
->condition('uri', $uri)
->execute()
->fetch(\PDO::FETCH_NUM);
if (!$row) {
return NULL;
}
[$entityTypeId, $entityId] = $row;
return $this->entityTypeManager->getStorage($entityTypeId)->load($entityId);
}
/**
* {@inheritdoc}
*/
public function getEntitiesByUris(array $uris): array {
$rows = $this->database->select('rdf_sync_uri')
->fields('rdf_sync_uri', ['uri', 'entity_type', 'entity_id'])
->condition('uri', $uris, 'IN')
->execute()
->fetchAll(\PDO::FETCH_NUM);
$byEntityTypeId = $result = [];
foreach ($rows as [$uri, $entityTypeId, $entityId]) {
$byEntityTypeId[$entityTypeId][] = $entityId;
}
foreach ($byEntityTypeId as $entityTypeId => $entityIds) {
foreach ($this->entityTypeManager->getStorage($entityTypeId)->loadMultiple($entityIds) as $entity) {
assert($entity instanceof ContentEntityInterface);
$fieldName = $this->getRdfUriFieldName(entity: $entity);
$result[$entity->get($fieldName)->value] = $entity;
}
}
// Preserve the original URIs order. Reduce first $uris to the loaded list.
$uris = array_intersect($uris, array_keys($result));
return array_merge(array_flip($uris), $result);
}
/**
* {@inheritdoc}
*/
public function getUrisByEntityType(string $entityTypeId, ?string $bundle = NULL): array {
$query = $this->database->select('rdf_sync_uri')
->fields('rdf_sync_uri', ['entity_id', 'uri'])
->condition('entity_type', $entityTypeId);
if ($bundle) {
$query->condition('bundle', $bundle);
}
return $query->execute()->fetchAllKeyed();
}
/**
* Returns the bundle mapping.
*
* @param string $entityTypeId
* The bundle's entity type ID.
* @param string $bundle
* The bundle.
*
* @return array|null
* The bundle mapping or NULL if no mapping is defined.
*/
protected function getBundleMapping(string $entityTypeId, string $bundle): ?array {
// Cover entity types without bundles.
$bundle = $bundle ?: $entityTypeId;
$bundleInfo = $this->entityTypeBundleInfo->getBundleInfo($entityTypeId)[$bundle] ?? [];
if (!$bundleInfo) {
return NULL;
}
return ($bundleInfo['rdf_sync'] ?? []) + [
'uri_field_name' => 'uri',
'uri_plugin' => NULL,
'fields' => [],
'namespaces' => [],
];
}
/**
* Resolves the entity type ID and the bundle, given the entity.
*
* @param string|null $entityTypeId
* The entity type ID passed by reference.
* @param string|null $bundle
* The bundle passed by reference.
* @param \Drupal\Core\Entity\ContentEntityInterface|null $entity
* The entity.
*/
protected function resolveEntityTypeAndBundle(?string &$entityTypeId, ?string &$bundle, ?ContentEntityInterface $entity): void {
if ($entity) {
if ($entityTypeId || $bundle) {
throw new \InvalidArgumentException('Cannot pass $entityTypeId or $bundle when $entity has been passed');
}
$entityTypeId = $entity->getEntityTypeId();
$bundle = $entity->bundle();
}
elseif (!($entityTypeId && $bundle)) {
throw new \InvalidArgumentException('Both, $entityTypeId and $bundle, should be passed when $entity is missed');
}
}
}
