Commit 7f8027f9 authored by Claudiu Cristea's avatar Claudiu Cristea
Browse files

Issue #3275936 by claudiu.cristea, idimopoulos: Support entity types w/o bundles

parent 4c6a4d40
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -21,10 +21,10 @@ services:
    - { name: route_processor_outbound, priority: 200 }
  sparql.graph_handler:
    class: Drupal\sparql_entity_storage\SparqlEntityStorageGraphHandler
    arguments: ['@entity_type.manager', '@event_dispatcher']
    arguments: ['@entity_type.manager', '@event_dispatcher', '@entity_type.bundle.info']
  sparql.field_handler:
    class: Drupal\sparql_entity_storage\SparqlEntityStorageFieldHandler
    arguments: ['@entity_type.manager', '@entity_field.manager', '@event_dispatcher']
    arguments: ['@entity_type.manager', '@entity_field.manager', '@event_dispatcher', '@entity_type.bundle.info']
  plugin.manager.sparql_entity_id:
    class: Drupal\sparql_entity_storage\SparqlEntityStorageEntityIdPluginManager
    arguments: ['@container.namespaces', '@cache.discovery', '@module_handler', '@entity_type.manager']
+1 −1
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ class SparqlCondition extends ConditionFundamentals implements SparqlConditionIn
    $this->fieldHandler = $sparql_field_handler;
    $this->languageManager = $language_manager;
    $this->typePredicates = $query->getEntityStorage()->getBundlePredicates();
    $this->bundleKey = $query->getEntityType()->getKey('bundle');
    $this->bundleKey = $query->getEntityType()->getKey('bundle') ?: $query->getEntityTypeId();
    $this->idKey = $query->getEntityType()->getKey('id');
    $this->labelKey = $query->getEntityType()->getKey('label');
    $this->fieldMappings = [
+15 −5
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\sparql_entity_storage\Driver\Database\sparql\ConnectionInterface;
use Drupal\sparql_entity_storage\Entity\Query\Sparql\SparqlArg;
use Drupal\sparql_entity_storage\Entity\SparqlGraph;
use Drupal\sparql_entity_storage\Entity\SparqlMapping;
use Drupal\sparql_entity_storage\Exception\DuplicatedIdException;
use EasyRdf\Graph;
use EasyRdf\Literal;
@@ -246,7 +247,7 @@ class SparqlEntityStorage extends ContentEntityStorageBase implements SparqlEnti
      $entities_values = $this->loadFromStorage($operation_ids, $graph_ids);
      if ($entities_values) {
        foreach ($entities_values as $id => $entity_values) {
          $bundle = $this->bundleKey ? $entity_values[$this->bundleKey][LanguageInterface::LANGCODE_DEFAULT] : FALSE;
          $bundle = $this->bundleKey ? $entity_values[$this->bundleKey][LanguageInterface::LANGCODE_DEFAULT] : NULL;
          $langcode_key = $this->getEntityType()->getKey('langcode');
          $translations = [];
          if (!empty($entities_values[$id][$langcode_key])) {
@@ -380,8 +381,10 @@ QUERY;
            continue;
          }

          // Map bundle and entity id.
          // Map bundle, entity ID and graph.
          if ($this->getEntityType()->hasKey('bundle')) {
            $return[$entity_id][$this->bundleKey][LanguageInterface::LANGCODE_DEFAULT] = $bundle;
          }
          $return[$entity_id][$this->idKey][LanguageInterface::LANGCODE_DEFAULT] = $entity_id;
          $return[$entity_id]['graph'][LanguageInterface::LANGCODE_DEFAULT] = $graph_id;

@@ -477,7 +480,7 @@ QUERY;
      return NULL;
    }

    // Since it is possible to map more than one bundles to the same uri, allow
    // Since it is possible to map more than one bundles to the same URI, allow
    // modules to handle this.
    $this->moduleHandler->alter('sparql_bundle_load', $entity_values, $bundles);
    if (count($bundles) > 1) {
@@ -863,6 +866,13 @@ QUERY;
      }
    }

    // Entities without bundles should add the rdf:type too.
    if (!$this->getEntityType()->hasKey('bundle')) {
      $predicate = reset($this->bundlePredicate);
      $mapping = SparqlMapping::loadByName($this->getEntityTypeId(), $bundle);
      $graph->add((string) $id, $predicate, $mapping->getRdfType());
    }

    // Give implementations a chance to alter the graph right before is saved.
    $this->alterGraph($graph, $entity);

@@ -958,7 +968,7 @@ QUERY;
    }

    // For the rest of the languages not computed above, simply add the
    // the translatable fields. This will prevent data loss from the database.
    // translatable fields. This will prevent data loss from the database.
    foreach (array_diff($languages, $processed) as $langcode) {
      if (!$entity->hasTranslation($langcode)) {
        continue;
+16 −13
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ declare(strict_types = 1);
namespace Drupal\sparql_entity_storage;

use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\sparql_entity_storage\Entity\Query\Sparql\SparqlArg;
@@ -112,6 +113,11 @@ class SparqlEntityStorageFieldHandler implements SparqlEntityStorageFieldHandler
   */
  protected EventDispatcherInterface $eventDispatcher;

  /**
   * The entity type bundle info service.
   */
  protected EntityTypeBundleInfoInterface $entityTypeBundleInfo;

  /**
   * Constructs a QueryFactory object.
   *
@@ -121,11 +127,14 @@ class SparqlEntityStorageFieldHandler implements SparqlEntityStorageFieldHandler
   *   The entity field manager.
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
   *   The event dispatcher service.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle info service.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, EventDispatcherInterface $event_dispatcher) {
  public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, EventDispatcherInterface $event_dispatcher, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
    $this->entityTypeManager = $entity_type_manager;
    $this->entityFieldManager = $entity_field_manager;
    $this->eventDispatcher = $event_dispatcher;
    $this->entityTypeBundleInfo = $entity_type_bundle_info;
  }

  /**
@@ -145,20 +154,14 @@ class SparqlEntityStorageFieldHandler implements SparqlEntityStorageFieldHandler
    if (empty($this->outboundMap[$entity_type_id]) && empty($this->inboundMap[$entity_type_id])) {
      $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);

      // @todo Support entity types without bundles or without bundle config
      // entities, in #3.
      // @see https://github.com/ec-europa/sparql_entity_storage/issues/3
      $bundle_type = $entity_type->getBundleEntityType();

      $this->outboundMap[$entity_type_id] = $this->inboundMap[$entity_type_id] = [];
      $this->outboundMap[$entity_type_id]['bundle_key'] = $this->inboundMap[$entity_type_id]['bundle_key'] = $entity_type->getKey('bundle');
      $bundle_entities = $this->entityTypeManager->getStorage($bundle_type)->loadMultiple();
      $this->outboundMap[$entity_type_id]['bundle_key'] = $this->inboundMap[$entity_type_id]['bundle_key'] = $entity_type->getKey('bundle') ?: NULL;

      foreach ($bundle_entities as $bundle_id => $bundle_entity) {
        $field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $bundle_entity->id());
        $mapping = SparqlMapping::loadByName($entity_type_id, $bundle_entity->id());
      foreach ($this->entityTypeBundleInfo->getBundleInfo($entity_type_id) as $bundle_id => $bundle_info) {
        $field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $bundle_id);
        $mapping = SparqlMapping::loadByName($entity_type_id, $bundle_id);
        if (!$bundle_mapping = $mapping->getRdfType()) {
          throw new \Exception("The {$bundle_entity->label()} SPARQL entity does not have an rdf_type set.");
          throw new \Exception("The {$bundle_info['label']} SPARQL entity does not have an rdf_type set.");
        }
        $this->outboundMap[$entity_type_id]['bundles'][$bundle_id] = $bundle_mapping;
        // More than one Drupal bundle can share the same mapped URI.
@@ -334,7 +337,7 @@ class SparqlEntityStorageFieldHandler implements SparqlEntityStorageFieldHandler
      $value = serialize($value);
    }

    if ($field_name == $outbound_map['bundle_key']) {
    if ($field_name === $outbound_map['bundle_key']) {
      $value = $this->getOutboundBundleValue($entity_type_id, $value);
    }

+16 −14
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ namespace Drupal\sparql_entity_storage;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\sparql_entity_storage\Entity\SparqlMapping;
use Drupal\sparql_entity_storage\Event\DefaultGraphsEvent;
@@ -39,6 +40,11 @@ class SparqlEntityStorageGraphHandler implements SparqlEntityStorageGraphHandler
   */
  protected EventDispatcherInterface $eventDispatcher;

  /**
   * The entity type bundle info service.
   */
  protected EntityTypeBundleInfoInterface $entityTypeBundleInfo;

  /**
   * Constructs a SPARQL graph handler object.
   *
@@ -46,10 +52,13 @@ class SparqlEntityStorageGraphHandler implements SparqlEntityStorageGraphHandler
   *   The entity type manager service.
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
   *   The event dispatcher service.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle info service.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher) {
  public function __construct(EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
    $this->entityTypeManager = $entity_type_manager;
    $this->eventDispatcher = $event_dispatcher;
    $this->entityTypeBundleInfo = $entity_type_bundle_info;
  }

  /**
@@ -128,8 +137,8 @@ class SparqlEntityStorageGraphHandler implements SparqlEntityStorageGraphHandler
   */
  public function getBundleGraphUri(string $entity_type_id, string $bundle, string $graph_id): ?string {
    $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
    $bundle_key = ($entity_type->hasKey('bundle') && $entity_type->getBundleEntityType()) ? $bundle : $entity_type_id;
    return $this->getEntityTypeGraphUris($entity_type_id)[$bundle_key][$graph_id] ?? NULL;
    $bundle = $entity_type->hasKey('bundle') ? $bundle : $entity_type_id;
    return $this->getEntityTypeGraphUris($entity_type_id)[$bundle][$graph_id] ?? NULL;
  }

  /**
@@ -137,17 +146,10 @@ class SparqlEntityStorageGraphHandler implements SparqlEntityStorageGraphHandler
   */
  public function getEntityTypeGraphUris(string $entity_type_id, ?array $limit_to_graph_ids = NULL): array {
    if (!isset($this->cache['structure'][$entity_type_id])) {
      $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
      if ($entity_type->hasKey('bundle') && ($bundle_entity_id = $entity_type->getBundleEntityType())) {
        $bundle_keys = array_values($this->entityTypeManager->getStorage($bundle_entity_id)->getQuery()->execute());
      }

      // Bundleless entity types use the entity type ID as the bundle ID.
      $bundle_keys = !empty($bundle_keys) ? $bundle_keys : [$entity_type_id];

      foreach ($bundle_keys as $bundle_key) {
        $graphs = ($mapping = SparqlMapping::loadByName($entity_type_id, $bundle_key)) ? $mapping->getGraphs() : [];
        $this->cache['structure'][$entity_type_id][$bundle_key] = $graphs;
      $bundle_ids = array_keys($this->entityTypeBundleInfo->getBundleInfo($entity_type_id));
      foreach ($bundle_ids as $bundle_id) {
        $graphs = ($mapping = SparqlMapping::loadByName($entity_type_id, $bundle_id)) ? $mapping->getGraphs() : [];
        $this->cache['structure'][$entity_type_id][$bundle_id] = $graphs;
      }
    }

Loading