Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add events for datastore pre-drop, drop, and import #4312

Merged
merged 14 commits into from
Oct 22, 2024
2 changes: 2 additions & 0 deletions modules/datastore/datastore.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ services:
- '@dkan.datastore.import_job_store_factory'
- '@dkan.datastore.service.resource_processor.dictionary_enforcer'
- '@dkan.metastore.resource_mapper'
- '@event_dispatcher'

dkan.datastore.service.post_import:
class: \Drupal\datastore\Service\PostImport
Expand Down Expand Up @@ -58,6 +59,7 @@ services:
- '@dkan.datastore.import_job_store_factory'
- '@dkan.datastore.database_table_factory'
- '@dkan.datastore.logger_channel'
- '@event_dispatcher'

dkan.datastore.logger_channel:
parent: logger.channel_base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ services:
- '@dkan.datastore.import_job_store_factory'
- '@dkan.datastore_mysql_import.database_table_factory'
- '@dkan.datastore.logger_channel'
- '@event_dispatcher'

dkan.datastore_mysql_import.database_table_factory:
class: \Drupal\datastore_mysql_import\Storage\MySqlDatabaseTableFactory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Drupal\datastore_mysql_import\Service\MysqlImport;
use Drupal\datastore_mysql_import\Storage\MySqlDatabaseTableFactory;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
* Mysql importer factory.
Expand Down Expand Up @@ -35,23 +36,30 @@ class MysqlImportFactory implements ImportFactoryInterface {
*/
private LoggerInterface $logger;

/**
* Event dispatcher service.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
private EventDispatcherInterface $eventDispatcher;

/**
* Constructor.
*/
public function __construct(
ImportJobStoreFactory $importJobStoreFactory,
MySqlDatabaseTableFactory $databaseTableFactory,
LoggerInterface $loggerChannel
LoggerInterface $loggerChannel,
EventDispatcherInterface $eventDispatcher,
) {
$this->importJobStoreFactory = $importJobStoreFactory;
$this->databaseTableFactory = $databaseTableFactory;
$this->logger = $loggerChannel;
$this->eventDispatcher = $eventDispatcher;
}

/**
* Inherited.
*
* @inheritdoc
* {@inheritDoc}
*/
public function getInstance(string $identifier, array $config = []) {
$resource = $config['resource'] ?? FALSE;
Expand All @@ -63,7 +71,8 @@ public function getInstance(string $identifier, array $config = []) {
$resource,
$this->importJobStoreFactory,
$this->databaseTableFactory,
$this->logger
$this->logger,
$this->eventDispatcher
);
$importer->setImporterClass(MysqlImport::class);
return $importer;
Expand Down
47 changes: 42 additions & 5 deletions modules/datastore/src/DatastoreService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,39 @@

namespace Drupal\datastore;

use Drupal\common\DataResource;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Queue\QueueFactory;
use Drupal\common\DataResource;
use Drupal\datastore\Events\DatastoreDroppedEvent;
use Drupal\datastore\Events\DatastorePreDropEvent;
use Drupal\datastore\Service\Factory\ImportFactoryInterface;
use Drupal\datastore\Service\ImportService;
use Drupal\datastore\Service\ResourceLocalizer;
use Drupal\datastore\Service\ResourceProcessor\DictionaryEnforcer;
use Drupal\datastore\Storage\ImportJobStoreFactory;
use Drupal\metastore\ResourceMapper;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
* Main services for the datastore.
*/
class DatastoreService implements ContainerInjectionInterface {

/**
* This event is triggered when the datastore is about to be dropped.
*
* The event data is a keyed array, identifier and version.
*/
const EVENT_DATASTORE_PRE_DROP = 'dkan_datastore_pre_drop';

/**
* This event is triggered when the datastore is dropped.
*
* The event data is a keyed array, identifier and version.
*/
const EVENT_DATASTORE_DROPPED = 'dkan_datastore_dropped';

/**
* Resource localizer for handling remote resource URLs.
*
Expand Down Expand Up @@ -60,6 +77,13 @@ class DatastoreService implements ContainerInjectionInterface {
*/
private ImportJobStoreFactory $importJobStoreFactory;

/**
* Event dispatcher service.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
private EventDispatcherInterface $eventDispatcher;

/**
* {@inheritdoc}
*/
Expand All @@ -70,7 +94,8 @@ public static function create(ContainerInterface $container) {
$container->get('queue'),
$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('dkan.metastore.resource_mapper'),
$container->get('event_dispatcher')
);
}

Expand All @@ -89,21 +114,25 @@ public static function create(ContainerInterface $container) {
* Dictionary Enforcer object.
* @param \Drupal\metastore\ResourceMapper $resourceMapper
* Resource mapper service.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
* Event dispatcher service.
*/
public function __construct(
ResourceLocalizer $resourceLocalizer,
ImportFactoryInterface $importServiceFactory,
QueueFactory $queue,
ImportJobStoreFactory $importJobStoreFactory,
DictionaryEnforcer $dictionaryEnforcer,
ResourceMapper $resourceMapper
ResourceMapper $resourceMapper,
EventDispatcherInterface $eventDispatcher,
) {
$this->resourceLocalizer = $resourceLocalizer;
$this->importServiceFactory = $importServiceFactory;
$this->queue = $queue;
$this->importJobStoreFactory = $importJobStoreFactory;
$this->dictionaryEnforcer = $dictionaryEnforcer;
$this->resourceMapper = $resourceMapper;
$this->eventDispatcher = $eventDispatcher;
}

/**
Expand Down Expand Up @@ -217,13 +246,13 @@ public function getImportService(DataResource $resource): ImportService {
/**
* Returns the Data Dictionary fields.
*
* @param string $identifier
* @param string|null $identifier
* A resource's identifier. Used when in reference mode.
*
* @return array|null
* An array of dictionary fields or null if no dictionary is in use.
*/
public function getDataDictionaryFields(string $identifier = NULL): ?array {
public function getDataDictionaryFields(?string $identifier = NULL): ?array {
return $this->dictionaryEnforcer->returnDataDictionaryFields($identifier);
}

Expand All @@ -242,9 +271,17 @@ public function drop(string $identifier, ?string $version = NULL, bool $remove_l
$resource = $this->resourceLocalizer->get($identifier, $version);

if ($storage = $this->getStorage($identifier, $version)) {
$this->eventDispatcher->dispatch(
new DatastorePreDropEvent($identifier, $version),
self::EVENT_DATASTORE_PRE_DROP
);
$storage->destruct();
$this->importJobStoreFactory->getInstance()
->remove(md5($resource->getUniqueIdentifier()));
$this->eventDispatcher->dispatch(
new DatastoreDroppedEvent($identifier, $version),
self::EVENT_DATASTORE_DROPPED
);
}

if ($remove_local_resource) {
Expand Down
2 changes: 2 additions & 0 deletions modules/datastore/src/EventSubscriber/DatastoreSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ public function drop(Event $event) {
$resource = $event->getData();
$id = md5(str_replace(DataResource::DEFAULT_SOURCE_PERSPECTIVE, ResourceLocalizer::LOCAL_FILE_PERSPECTIVE, $resource->getUniqueIdentifier()));
try {
// @todo Check if the datastore exists before dropping. Don't log an
// error if it wasn't there to begin with.
$this->datastoreService->drop($resource->getIdentifier(), $resource->getVersion());
$this->logger->notice('Dropping datastore for @id', ['@id' => $id]);
}
Expand Down
12 changes: 12 additions & 0 deletions modules/datastore/src/Events/DatastoreDroppedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Drupal\datastore\Events;

/**
* Event object for after we've dropped a datastore.
*
* @see \Drupal\datastore\DatastoreService::EVENT_DATASTORE_DROPPED
*/
class DatastoreDroppedEvent extends DatastoreEventBase {

}
53 changes: 53 additions & 0 deletions modules/datastore/src/Events/DatastoreEventBase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Drupal\datastore\Events;

use Drupal\Component\EventDispatcher\Event;

/**
* Event base class for the datastore module.
*/
class DatastoreEventBase extends Event implements DatastoreEventInterface {

/**
* The datastore identifier.
*
* @var string
*/
private string $identifier;

/**
* The datastore version.
*
* @var string|null
*/
private ?string $version;

/**
* Constructor.
*
* @param string $identifier
* The datastore identifier.
* @param string|null $version
* (Optional) The datastore version.
*/
public function __construct(string $identifier, ?string $version) {
$this->identifier = $identifier;
$this->version = $version;
}

/**
* {@inheritDoc}
*/
public function getIdentifier(): string {
return $this->identifier;
}

/**
* {@inheritDoc}
*/
public function getVersion(): ?string {
return $this->version;
}

}
26 changes: 26 additions & 0 deletions modules/datastore/src/Events/DatastoreEventInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Drupal\datastore\Events;

/**
* Event base class for the datastore module.
*/
interface DatastoreEventInterface {

/**
* Get the datastore identifier.
*
* @return string
* The datastore identifier.
*/
public function getIdentifier(): string;

/**
* Get the datastore version.
*
* @return string|null
* The datastore version, or NULL if none was provided.
*/
public function getVersion(): ?string;

}
12 changes: 12 additions & 0 deletions modules/datastore/src/Events/DatastoreImportedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Drupal\datastore\Events;

/**
* Event object for when a datastore has finished importing.
*
* @see \Drupal\datastore\Service\ImportService::EVENT_DATASTORE_IMPORTED
*/
class DatastoreImportedEvent extends DatastoreEventBase {

}
12 changes: 12 additions & 0 deletions modules/datastore/src/Events/DatastorePreDropEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Drupal\datastore\Events;

/**
* Event object for when we're about to drop a datastore.
*
* @see \Drupal\datastore\DatastoreService::EVENT_DATASTORE_PRE_DROP
*/
class DatastorePreDropEvent extends DatastoreEventBase {

}
19 changes: 14 additions & 5 deletions modules/datastore/src/Service/Factory/ImportServiceFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Drupal\datastore\Storage\DatabaseTableFactory;
use Drupal\datastore\Storage\ImportJobStoreFactory;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
* Create an importer object for a given resource.
Expand Down Expand Up @@ -33,31 +34,39 @@ class ImportServiceFactory implements ImportFactoryInterface {
*/
private LoggerInterface $logger;

/**
* Event dispatcher service.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
private EventDispatcherInterface $eventDispatcher;

/**
* Constructor.
*/
public function __construct(
ImportJobStoreFactory $importJobStoreFactory,
DatabaseTableFactory $databaseTableFactory,
LoggerInterface $loggerChannel
LoggerInterface $loggerChannel,
EventDispatcherInterface $eventDispatcher,
) {
$this->importJobStoreFactory = $importJobStoreFactory;
$this->databaseTableFactory = $databaseTableFactory;
$this->logger = $loggerChannel;
$this->eventDispatcher = $eventDispatcher;
}

/**
* Inherited.
*
* @inheritdoc
* {@inheritDoc}
*/
public function getInstance(string $identifier, array $config = []) {
if ($resource = $config['resource'] ?? FALSE) {
return new ImportService(
$resource,
$this->importJobStoreFactory,
$this->databaseTableFactory,
$this->logger
$this->logger,
$this->eventDispatcher,
);
}
throw new \Exception("config['resource'] is required");
Expand Down
Loading