diff --git a/modules/datastore/datastore.services.yml b/modules/datastore/datastore.services.yml index 3bf48b37fe..3aef3143c4 100644 --- a/modules/datastore/datastore.services.yml +++ b/modules/datastore/datastore.services.yml @@ -9,6 +9,7 @@ services: - '@dkan.datastore.service.resource_processor.dictionary_enforcer' - '@dkan.metastore.resource_mapper' - '@event_dispatcher' + - '@dkan.metastore.reference_lookup' dkan.datastore.service.post_import: class: \Drupal\datastore\Service\PostImport diff --git a/modules/datastore/src/DatastoreService.php b/modules/datastore/src/DatastoreService.php index 02230c3383..9f7239094b 100644 --- a/modules/datastore/src/DatastoreService.php +++ b/modules/datastore/src/DatastoreService.php @@ -10,6 +10,7 @@ use Drupal\datastore\Service\Factory\ImportFactoryInterface; use Drupal\datastore\Service\ImportService; use Drupal\datastore\Service\ResourceLocalizer; +use Drupal\metastore\Reference\ReferenceLookup; use Drupal\datastore\Service\ResourceProcessor\DictionaryEnforcer; use Drupal\datastore\Storage\ImportJobStoreFactory; use Drupal\metastore\ResourceMapper; @@ -84,6 +85,13 @@ class DatastoreService implements ContainerInjectionInterface { */ private EventDispatcherInterface $eventDispatcher; + /** + * Reference lookup service. + * + * @var \Drupal\metastore\Reference\ReferenceLookup + */ + protected $referenceLookup; + /** * {@inheritdoc} */ @@ -95,7 +103,8 @@ public static function create(ContainerInterface $container) { $container->get('dkan.datastore.import_job_store_factory'), $container->get('dkan.datastore.service.resource_processor.dictionary_enforcer'), $container->get('dkan.metastore.resource_mapper'), - $container->get('event_dispatcher') + $container->get('event_dispatcher'), + $container->get('dkan.metastore.reference_lookup') ); } @@ -116,6 +125,8 @@ public static function create(ContainerInterface $container) { * Resource mapper service. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher * Event dispatcher service. + * @param \Drupal\metastore\Reference\ReferenceLookup $referenceLookup + * The reference lookup service. */ public function __construct( ResourceLocalizer $resourceLocalizer, @@ -125,6 +136,7 @@ public function __construct( DictionaryEnforcer $dictionaryEnforcer, ResourceMapper $resourceMapper, EventDispatcherInterface $eventDispatcher, + ReferenceLookup $referenceLookup, ) { $this->resourceLocalizer = $resourceLocalizer; $this->importServiceFactory = $importServiceFactory; @@ -133,6 +145,7 @@ public function __construct( $this->dictionaryEnforcer = $dictionaryEnforcer; $this->resourceMapper = $resourceMapper; $this->eventDispatcher = $eventDispatcher; + $this->referenceLookup = $referenceLookup; } /** @@ -297,6 +310,10 @@ public function drop(string $identifier, ?string $version = NULL, bool $remove_l if ($remove_local_resource) { $this->resourceLocalizer->remove($identifier, $version); } + + // Invalidate cache tag. + $uid = $resource->getIdentifier() . '__' . $resource->getVersion(); + $this->invalidateCacheTags($uid . '__source'); } /** @@ -360,4 +377,14 @@ public function getQueueFactory(): QueueFactory { return $this->queue; } + /** + * Invalidate all appropriate cache tags for this resource. + * + * @param mixed $resourceId + * A resource ID. + */ + protected function invalidateCacheTags(mixed $resourceId) { + $this->referenceLookup->invalidateReferencerCacheTags('distribution', $resourceId, 'downloadURL'); + } + } diff --git a/modules/datastore/tests/src/Kernel/DatastoreServiceEventsTest.php b/modules/datastore/tests/src/Kernel/DatastoreServiceEventsTest.php index a08b565cac..4ef79b75a5 100644 --- a/modules/datastore/tests/src/Kernel/DatastoreServiceEventsTest.php +++ b/modules/datastore/tests/src/Kernel/DatastoreServiceEventsTest.php @@ -25,10 +25,17 @@ */ class DatastoreServiceEventsTest extends KernelTestBase implements EventSubscriberInterface { + protected $strictConfigSchema = FALSE; + protected static $modules = [ 'common', 'datastore', 'metastore', + 'node', + 'user', + 'field', + 'text', + 'system', ]; /** @@ -79,6 +86,9 @@ public function register(ContainerBuilder $container) { } public function testEvents() { + $this->installEntitySchema('node'); + $this->installConfig(['node']); + $this->installConfig(['metastore']); // Mock a data resource. $data_resource = $this->getMockBuilder(DataResource::class) ->disableOriginalConstructor() @@ -130,6 +140,7 @@ public function testEvents() { $this->container->get('dkan.datastore.service.resource_processor.dictionary_enforcer'), $this->container->get('dkan.metastore.resource_mapper'), $this->container->get('event_dispatcher'), + $this->container->get('dkan.metastore.reference_lookup'), ]) ->onlyMethods(['getStorage']) ->getMock(); diff --git a/modules/datastore/tests/src/Kernel/Plugin/QueueWorker/ImportQueueWorkerTest.php b/modules/datastore/tests/src/Kernel/Plugin/QueueWorker/ImportQueueWorkerTest.php index 823e47d610..807320455f 100644 --- a/modules/datastore/tests/src/Kernel/Plugin/QueueWorker/ImportQueueWorkerTest.php +++ b/modules/datastore/tests/src/Kernel/Plugin/QueueWorker/ImportQueueWorkerTest.php @@ -48,6 +48,7 @@ public function testErrorPath() { $this->container->get('dkan.datastore.service.resource_processor.dictionary_enforcer'), $this->container->get('dkan.metastore.resource_mapper'), $this->container->get('event_dispatcher'), + $this->container->get('dkan.metastore.reference_lookup'), ]) ->onlyMethods(['import']) ->getMock(); @@ -95,6 +96,7 @@ public function testRequeue() { $this->container->get('dkan.datastore.service.resource_processor.dictionary_enforcer'), $this->container->get('dkan.metastore.resource_mapper'), $this->container->get('event_dispatcher'), + $this->container->get('dkan.metastore.reference_lookup'), ]) ->onlyMethods(['import']) ->getMock(); @@ -226,6 +228,7 @@ public function testAlreadyImported() { $this->container->get('dkan.datastore.service.resource_processor.dictionary_enforcer'), $this->container->get('dkan.metastore.resource_mapper'), $this->container->get('event_dispatcher'), + $this->container->get('dkan.metastore.reference_lookup'), ]) ->onlyMethods(['getStorage']) ->getMock(); diff --git a/modules/datastore/tests/src/Unit/DatastoreServiceTest.php b/modules/datastore/tests/src/Unit/DatastoreServiceTest.php index 64bd27381e..302567b0e2 100644 --- a/modules/datastore/tests/src/Unit/DatastoreServiceTest.php +++ b/modules/datastore/tests/src/Unit/DatastoreServiceTest.php @@ -15,6 +15,7 @@ use Drupal\datastore\Service\ImportService; use Drupal\datastore\Service\Info\ImportInfoList; use Drupal\datastore\Service\ResourceLocalizer; +use Drupal\metastore\Reference\ReferenceLookup; use Drupal\datastore\Service\ResourceProcessor\DictionaryEnforcer; use Drupal\datastore\Storage\DatabaseTable; use Drupal\metastore\ResourceMapper; @@ -69,8 +70,10 @@ public function testDrop() { ->add(ResourceLocalizer::class, 'get', $resource) ->add(ResourceMapper::class, 'get', $resource) ->add(JobStoreFactory::class, 'getInstance', JobStore::class) + ->add(JobStore::class, 'remove', TRUE) ->add(ImportJobStoreFactory::class, 'getInstance', JobStore::class) - ->add(JobStore::class, 'remove', TRUE); + ->add(ReferenceLookup::class, 'getReferencers', [$resource->getIdentifier()]) + ->add(ReferenceLookup::class, 'invalidateReferencerCacheTags'); $service = DatastoreService::create($mockChain->getMock()); // These are all valid ways to call drop(). @@ -106,6 +109,7 @@ private function getCommonChain() { ->add('dkan.datastore.import_job_store_factory', ImportJobStoreFactory::class) ->add('dkan.datastore.import_info_list', ImportInfoList::class) ->add('dkan.datastore.service.resource_processor.dictionary_enforcer', DictionaryEnforcer::class) + ->add('dkan.metastore.reference_lookup', ReferenceLookup::class) ->index(0); return (new Chain($this)) diff --git a/modules/datastore/tests/src/Unit/Service/DatastoreQueryTest.php b/modules/datastore/tests/src/Unit/Service/DatastoreQueryTest.php index 0aba0301d0..b97cc77c1f 100644 --- a/modules/datastore/tests/src/Unit/Service/DatastoreQueryTest.php +++ b/modules/datastore/tests/src/Unit/Service/DatastoreQueryTest.php @@ -28,6 +28,7 @@ use Drupal\metastore\Storage\DataFactory; use Drupal\Tests\common\Unit\Storage\QueryDataProvider as QueryData; use Drupal\datastore\Service\ResourceProcessor\DictionaryEnforcer; +use Drupal\metastore\Reference\ReferenceLookup; /** * @group dkan @@ -204,6 +205,7 @@ public function getCommonMockChain() { ->add('dkan.metastore.storage', DataFactory::class) ->add('dkan.datastore.import_info_list', ImportInfoList::class) ->add('dkan.datastore.service.resource_processor.dictionary_enforcer', DictionaryEnforcer::class) + ->add('dkan.metastore.reference_lookup', ReferenceLookup::class) ->index(0); $resource_metadata = '{"data":{"%Ref:downloadURL":[{"data":{"identifier":"qwerty","version":"uiop"}}]}}'; @@ -223,7 +225,9 @@ public function getCommonMockChain() { ->add(DatabaseTable::class, "query", $queryResult, 'DatabaseTableQuery') ->add(DatabaseTable::class, "getSchema", ["fields" => ["a" => "a", "b" => "b"]]) ->add(DatabaseTable::class, "getTableName", "table2") - ->add(DatabaseTable::class, "primaryKey", "record_number"); + ->add(DatabaseTable::class, "primaryKey", "record_number") + ->add(ReferenceLookup::class, 'getReferencers', [$resource->getIdentifier()]) + ->add(ReferenceLookup::class, 'invalidateReferencerCacheTags'); }