Skip to content
Snippets Groups Projects
Commit d2e38f25 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3358812 by alexpott, daniel.bosen: Add revision ID and VG Wort counter...

Issue #3358812 by alexpott, daniel.bosen: Add revision ID and VG Wort counter ID to vgwort_entity_registration
parent 83025892
No related branches found
No related tags found
1 merge request!24Resolve #3358812 "Add revision"
......@@ -9,6 +9,7 @@ use Drupal\advancedqueue\Plugin\AdvancedQueue\Backend\SupportsLoadingJobsInterfa
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\vgwort\Plugin\AdvancedQueue\JobType\RegistrationNotification;
/**
......@@ -31,32 +32,78 @@ final class EntityJobMapper {
*/
protected Connection $connection;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* Constructs a EntityJobMapper object.
*
* @param \Drupal\Core\Database\Connection $connection
* The database connection which will be used to check the IP against.
* The database connection to sort VG Wort entity registrations.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
*/
public function __construct(Connection $connection) {
public function __construct(Connection $connection, EntityTypeManagerInterface $entityTypeManager) {
$this->connection = $connection;
$this->entityTypeManager = $entityTypeManager;
}
/**
* Marks a job as successful in the map.
*
* This method should only be called after to sending the entity to VG Wort.
*
* @param \Drupal\advancedqueue\Job $job
* The job to insert or update.
* @param int $success_timestamp
* The timestamp to set success_timestamp to.
* @param string $counter_id
* The counter ID sent to VG Wort.
* @param int|null $revision_id
* The revision ID for the entity that was sent to VGWort. Must be provided
* if the entity type is revisionable and the success_timestamp is being
* set.
*
* @return $this
* The entity job mapper.
*/
public function markSuccessful(Job $job, int $success_timestamp, string $counter_id, ?int $revision_id): self {
[$entity_type, $entity_id] = RegistrationNotification::getEntityInfoFromJob($job);
// Ensure the revision ID is provided for revisionable entities.
if ($revision_id === NULL && $this->entityTypeManager->getDefinition($entity_type)->isRevisionable()) {
throw new \LogicException(sprintf('The revision ID must be supplied when marking %s entities as successfully sent to VG Wort', $entity_type));
}
$this->connection->merge(self::TABLE)
->keys(['entity_type' => $entity_type, 'entity_id' => $entity_id, 'counter_id' => $counter_id])
->fields(['revision_id' => $revision_id, 'job_id' => $job->getId(), 'success_timestamp' => $success_timestamp])
->execute();
return $this;
}
/**
* Inserts or updates a row in the map.
* Adds a job to the map.
*
* This method should only be called prior to sending the entity to VG Wort.
*
* @param \Drupal\advancedqueue\Job $job
* The job to insert or update.
* @param int|null $success_timestamp
* (optional) The timestamp to set success_timestamp to. Defaults to NULL.
* @param string $counter_id
* The counter ID for the entity.
*
* @return $this
* The entity job mapper.
*/
public function merge(Job $job, ?int $success_timestamp = NULL): self {
public function addJobToMap(Job $job, string $counter_id) {
[$entity_type, $entity_id] = RegistrationNotification::getEntityInfoFromJob($job);
$this->connection->merge(self::TABLE)
->keys(['entity_type' => $entity_type, 'entity_id' => $entity_id])
->fields(['job_id' => $job->getId(), 'success_timestamp' => $success_timestamp])
->keys(['entity_type' => $entity_type, 'entity_id' => $entity_id, 'counter_id' => $counter_id])
->fields(['job_id' => $job->getId()])
->execute();
return $this;
}
......@@ -74,11 +121,11 @@ final class EntityJobMapper {
* The job object. NULL if a new job needs to be queued.
*/
public function getJob(EntityInterface $entity): ?Job {
// The table might not yet exist.
$result = $this->connection->select(self::TABLE, 'map')
->fields('map', ['entity_type', 'entity_id', 'job_id', 'success_timestamp'])
->condition('entity_type', $entity->getEntityTypeId())
->condition('entity_id', $entity->id())
->condition('counter_id', $entity->vgwort_counter_id->value)
->execute()
->fetchObject();
......@@ -108,6 +155,30 @@ final class EntityJobMapper {
return NULL;
}
/**
* Gets the revision IDs and counter IDs sent to VG Wort for an entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to check.
*
* @return string[]
* A list of counter IDs sent to VG Wort for the entity keyed by the
* revision ID.
*/
public function getRevisionsSent(EntityInterface $entity): array {
$result = $this->connection->select(self::TABLE, 'map')
->fields('map', ['revision_id', 'counter_id'])
->condition('entity_type', $entity->getEntityTypeId())
->condition('entity_id', $entity->id())
->isNotNull('success_timestamp')
->execute();
$revisions = [];
foreach ($result as $row) {
$revisions[(int) $row->revision_id] = $row->counter_id;
}
return $revisions;
}
/**
* Cleans up when an entity is deleted.
*
......@@ -172,6 +243,19 @@ final class EntityJobMapper {
'default' => '',
'description' => 'The entity ID.',
],
'counter_id' => [
'type' => 'varchar_ascii',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'The counter ID',
],
'revision_id' => [
'type' => 'int',
'not null' => FALSE,
'default' => NULL,
'description' => 'The entity revision ID of the version sent to VG Wort (if available).',
],
'job_id' => [
'type' => 'int',
'size' => 'big',
......@@ -186,7 +270,7 @@ final class EntityJobMapper {
'unsigned' => TRUE,
],
],
'primary key' => ['entity_type', 'entity_id'],
'primary key' => ['entity_type', 'entity_id', 'counter_id'],
'indexes' => [
'job_id' => ['job_id'],
],
......
......@@ -91,7 +91,7 @@ class EntityQueuer {
$job = RegistrationNotification::createJob($entity);
$queue->enqueueJob($job, $delay ?? $this->getDefaultDelay());
$this->entityJobMapper->merge($job);
$this->entityJobMapper->addJobToMap($job, $entity->vgwort_counter_id->value);
return TRUE;
}
......
......@@ -13,6 +13,7 @@ use Drupal\Core\Config\Config;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\RevisionableInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\vgwort\EntityJobMapper;
use Drupal\vgwort\Exception\NewMessageException;
......@@ -164,7 +165,8 @@ class RegistrationNotification extends JobTypeBase implements ContainerFactoryPl
if ($response->getStatusCode() >= 400) {
return $this->createJobFailure($response);
}
$this->entityJobMapper->merge($job, $this->time->getCurrentTime());
$revision_id = $entity instanceof RevisionableInterface ? $entity->getRevisionId() : NULL;
$this->entityJobMapper->markSuccessful($job, $this->time->getCurrentTime(), $entity->vgwort_counter_id->value, $revision_id);
return JobResult::success();
}
......
......@@ -7,6 +7,9 @@
use Drupal\Core\Database\Database;
use Drupal\Core\Serialization\Yaml;
use Drupal\vgwort\EntityJobMapper;
include_once __DIR__ . '/../../vgwort.install';
$connection = Database::getConnection();
......@@ -121,3 +124,6 @@ $connection->insert('key_value')
'value' => $entity_type,
])
->execute();
// Create the vgwort_entity_registration table.
$connection->schema()->createTable(EntityJobMapper::TABLE, _vgwort_schema_definition_20001());
<?php
/**
* @file
* Database to mimic the installation of the VG Wort module.
*/
use Drupal\Core\Database\Database;
use Drupal\Core\Serialization\Yaml;
use Drupal\vgwort\EntityJobMapper;
include_once __DIR__ . '/../../vgwort.install';
$connection = Database::getConnection();
// Set the schema version.
$connection->merge('key_value')
->condition('collection', 'system.schema')
->condition('name', 'vgwort')
->fields([
'collection' => 'system.schema',
'name' => 'vgwort',
'value' => 'i:20003;',
])
->execute();
// Update core.extension.
$extensions = $connection->select('config')
->fields('config', ['data'])
->condition('collection', '')
->condition('name', 'core.extension')
->execute()
->fetchField();
$extensions = unserialize($extensions);
$extensions['module']['advancedqueue'] = 0;
$extensions['module']['vgwort'] = 0;
$connection->update('config')
->fields([
'data' => serialize($extensions),
])
->condition('collection', '')
->condition('name', 'core.extension')
->execute();
// Install VG Wort settings so tht entities can get a counter ID.
$config = <<<YAML
username: ''
password: ''
prefix: vgzm
publisher_id: '123456'
image_domain: 'http://example.com'
registration_wait_days: 14
queue_retry_time: 86400
entity_types:
node:
view_mode: full
test_mode: false
legal_rights:
distribution: false
public_access: false
reproduction: false
declaration_of_granting: false
other_public_communication: false
YAML;
$connection->insert('config')
->fields([
'collection',
'name',
'data',
])
->values([
'collection' => '',
'name' => 'vgwort.settings',
'data' => serialize(Yaml::decode($config)),
])
->execute();
// Install VG Wort queue are they were for the third beta release.
$config = <<<YAML
uuid: 34e0cd0a-8230-41d2-a724-0717ab69996f
langcode: en
status: true
dependencies:
enforced:
module:
- vgwort
id: vgwort
label: 'VG Wort'
backend: database
backend_configuration:
lease_time: 300
processor: daemon
processing_time: 90
locked: false
threshold:
type: 0
limit: 0
state: all
YAML;
$connection->insert('config')
->fields([
'collection',
'name',
'data',
])
->values([
'collection' => '',
'name' => 'advancedqueue.advancedqueue_queue.vgwort',
'data' => serialize(Yaml::decode($config)),
])
->execute();
$entity_type = 'O:42:"Drupal\Core\Config\Entity\ConfigEntityType":43:{s:5:" * id";s:19:"advancedqueue_queue";s:8:" * class";s:33:"Drupal\advancedqueue\Entity\Queue";s:11:" * provider";s:13:"advancedqueue";s:15:" * static_cache";b:0;s:15:" * render_cache";b:1;s:19:" * persistent_cache";b:1;s:14:" * entity_keys";a:8:{s:2:"id";s:2:"id";s:5:"label";s:5:"label";s:4:"uuid";s:4:"uuid";s:8:"revision";s:0:"";s:6:"bundle";s:0:"";s:8:"langcode";s:8:"langcode";s:16:"default_langcode";s:16:"default_langcode";s:29:"revision_translation_affected";s:29:"revision_translation_affected";}s:16:" * originalClass";s:33:"Drupal\advancedqueue\Entity\Queue";s:11:" * handlers";a:5:{s:6:"access";s:46:"Drupal\advancedqueue\QueueAccessControlHandler";s:12:"list_builder";s:37:"Drupal\advancedqueue\QueueListBuilder";s:4:"form";a:3:{s:3:"add";s:35:"Drupal\advancedqueue\Form\QueueForm";s:4:"edit";s:35:"Drupal\advancedqueue\Form\QueueForm";s:6:"delete";s:35:"Drupal\Core\Entity\EntityDeleteForm";}s:14:"route_provider";a:1:{s:7:"default";s:51:"Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider";}s:7:"storage";s:45:"Drupal\Core\Config\Entity\ConfigEntityStorage";}s:19:" * admin_permission";s:24:"administer advancedqueue";s:25:" * permission_granularity";s:11:"entity_type";s:8:" * links";a:4:{s:8:"add-form";s:31:"/admin/config/system/queues/add";s:9:"edit-form";s:56:"/admin/config/system/queues/manage/{advancedqueue_queue}";s:11:"delete-form";s:63:"/admin/config/system/queues/manage/{advancedqueue_queue}/delete";s:10:"collection";s:27:"/admin/config/system/queues";}s:21:" * bundle_entity_type";N;s:12:" * bundle_of";N;s:15:" * bundle_label";N;s:13:" * base_table";N;s:22:" * revision_data_table";N;s:17:" * revision_table";N;s:13:" * data_table";N;s:11:" * internal";b:0;s:15:" * translatable";b:0;s:19:" * show_revision_ui";b:0;s:8:" * label";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:5:"Queue";s:12:" * arguments";a:0:{}s:10:" * options";a:0:{}}s:19:" * label_collection";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:6:"Queues";s:12:" * arguments";a:0:{}s:10:" * options";a:0:{}}s:17:" * label_singular";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:5:"queue";s:12:" * arguments";a:0:{}s:10:" * options";a:0:{}}s:15:" * label_plural";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:6:"queues";s:12:" * arguments";a:0:{}s:10:" * options";a:0:{}}s:14:" * label_count";a:3:{s:8:"singular";s:12:"@count queue";s:6:"plural";s:13:"@count queues";s:7:"context";N;}s:15:" * uri_callback";N;s:8:" * group";s:13:"configuration";s:14:" * group_label";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:13:"Configuration";s:12:" * arguments";a:0:{}s:10:" * options";a:1:{s:7:"context";s:17:"Entity type group";}}s:22:" * field_ui_base_route";N;s:26:" * common_reference_target";b:0;s:22:" * list_cache_contexts";a:0:{}s:18:" * list_cache_tags";a:1:{i:0;s:31:"config:advancedqueue_queue_list";}s:14:" * constraints";a:0:{}s:13:" * additional";a:0:{}s:14:" * _serviceIds";a:0:{}s:18:" * _entityStorages";a:0:{}s:20:" * stringTranslation";N;s:16:" * config_prefix";s:19:"advancedqueue_queue";s:14:" * lookup_keys";a:1:{i:0;s:4:"uuid";}s:16:" * config_export";a:8:{i:0;s:2:"id";i:1;s:5:"label";i:2;s:7:"backend";i:3;s:21:"backend_configuration";i:4;s:9:"processor";i:5;s:15:"processing_time";i:6;s:9:"threshold";i:7;s:6:"locked";}s:21:" * mergedConfigExport";a:0:{}}';
$connection->insert('key_value')
->fields([
'collection',
'name',
'value',
])
->values([
'collection' => 'entity.definitions.installed',
'name' => 'advancedqueue_queue.entity_type',
'value' => $entity_type,
])
->execute();
// Create the vgwort_entity_registration table.
$connection->schema()->createTable(EntityJobMapper::TABLE, _vgwort_schema_definition_20001());
<?php
namespace Drupal\Tests\vgwort\Functional;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
use Drupal\vgwort\EntityJobMapper;
/**
* Tests the VG Wort module.
*
* @group vgwort
*/
class VGWortUpdateBeta4Test extends UpdatePathTestBase {
use AssertPageCacheContextsAndTagsTrait;
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
protected function setUp(): void {
parent::setUp();
\Drupal::service('update.post_update_registry')->registerInvokedUpdates([
'vgwort_post_update_add_node_to_entity_types',
'vgwort_post_update_set_test_mode',
'vgwort_post_update_create_queue',
'vgwort_post_update_add_legal_rights_to_config',
'vgwort_post_update_daemon_queue',
]);
// Create some fake data in the map so that vgwort_update_20005() has some
// to update.
\Drupal::database()->insert(EntityJobMapper::TABLE)
->fields(['entity_type', 'entity_id', 'job_id', 'success_timestamp'])
->values(['entity_type' => 'node', 'entity_id' => 1, 'job_id' => 1, 'success_timestamp' => NULL])
->values(['entity_type' => 'node', 'entity_id' => 2, 'job_id' => 2, 'success_timestamp' => 100000])
->values(['entity_type' => 'node', 'entity_id' => 3, 'job_id' => 3, 'success_timestamp' => NULL])
->values(['entity_type' => 'node', 'entity_id' => 4, 'job_id' => 4, 'success_timestamp' => 100000])
->values(['entity_type' => 'node', 'entity_id' => 5, 'job_id' => 5, 'success_timestamp' => 100000])
->values(['entity_type' => 'node', 'entity_id' => 8, 'job_id' => 6, 'success_timestamp' => NULL])
->execute();
}
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles[] = $this->root . '/core/modules/system/tests/fixtures/update/drupal-9.4.0.filled.standard.php.gz';
$this->databaseDumpFiles[] = __DIR__ . '/../../fixtures/install_vgwort_for_update_testing_2.0.0-beta4.php';
}
/**
* Tests vgwort_update_20004() and vgwort_update_20005().
*/
public function testVgWortUpdates(): void {
$schema = \Drupal::database()->schema();
$find_primary_key_columns = new \ReflectionMethod(get_class($schema), 'findPrimaryKeyColumns');
$find_primary_key_columns->setAccessible(TRUE);
// Ensure install_vgwort_for_update_testing_2.0.0-beta4.php is working.
$this->assertTrue($schema->tableExists(EntityJobMapper::TABLE));
$this->assertFalse($schema->fieldExists(EntityJobMapper::TABLE, 'revision_id'));
$this->assertFalse($schema->fieldExists(EntityJobMapper::TABLE, 'counter_id'));
$this->assertEquals(['entity_type', 'entity_id'], $find_primary_key_columns->invoke($schema, EntityJobMapper::TABLE));
// Run updates and test them.
$this->runUpdates();
$schema = \Drupal::database()->schema();
$this->assertTrue($schema->fieldExists(EntityJobMapper::TABLE, 'revision_id'));
$this->assertTrue($schema->fieldExists(EntityJobMapper::TABLE, 'counter_id'));
$this->assertEquals(['entity_type', 'entity_id', 'counter_id'], $find_primary_key_columns->invoke($schema, EntityJobMapper::TABLE));
$this->assertMapUpdated(1, 'vgzm.123456-0b164728-be64-41b3-b610-16be2ec381ef', NULL);
$this->assertMapUpdated(2, 'vgzm.123456-636df636-7fb0-4435-b325-37d5e4197154', '3');
$this->assertMapUpdated(3, 'vgzm.123456-8d55f6ae-f1e0-427d-aa09-9a302434da09', NULL);
$this->assertMapUpdated(4, 'vgzm.123456-2628d7e4-8e93-4e67-8b00-c773651d7d37', '5');
$this->assertMapUpdated(8, 'vgzm.123456-ebbf8389-3b6d-4469-b500-e74117a0e0b3', NULL);
// Ensure a row for an entity that does not exist has been deleted.
$row = \Drupal::database()->select(EntityJobMapper::TABLE, 'map')
->fields('map')
->condition('entity_type', 'node')
->condition('entity_id', 5)
->execute()->fetchObject();
$this->assertFalse($row);
}
/**
* Ensures the map has the expected values after the update.
*
* @param int $nid
* The node ID to check the map table values for.
* @param string $counter_id
* The expected counter ID.
* @param string|null $revision_id
* The expected revision ID.
*/
private function assertMapUpdated(int $nid, string $counter_id, ?string $revision_id): void {
$row = \Drupal::database()->select(EntityJobMapper::TABLE, 'map')
->fields('map', ['counter_id', 'revision_id'])
->condition('entity_type', 'node')
->condition('entity_id', $nid)
->execute()->fetchObject();
$this->assertSame($counter_id, $row->counter_id, "Counter ID is the expected value for node $nid");
$this->assertSame($revision_id, $row->revision_id, "Revision ID is the expected value for node $nid");
}
}
......@@ -245,6 +245,10 @@ class EntityQueueTest extends VgWortKernelTestBase {
$jobs[Job::STATE_SUCCESS] = '1';
$jobs[Job::STATE_FAILURE] = '1';
$this->assertSame($jobs, $queue_backend->countJobs());
// Ensure the revision information is only available for entities that have
// been sent to VG Wort.
$this->assertSame([1 => $entity->vgwort_counter_id->value], $this->container->get('vgwort.entity_job_mapper')->getRevisionsSent($entity));
$this->assertSame([], $this->container->get('vgwort.entity_job_mapper')->getRevisionsSent($another_entity));
// We maintain a map separate from the queue to ensure we know when an
// entity has been successfully sent to VG Wort.
......
......@@ -5,6 +5,9 @@
* Contains install and update functions for VG Wort module.
*/
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\RevisionableInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\vgwort\EntityJobMapper;
/**
......@@ -14,12 +17,58 @@ function vgwort_schema(): array {
return [EntityJobMapper::TABLE => EntityJobMapper::schemaDefinition()];
}
/**
* Gets the schema definition as it was for 20001 for the map table.
*
* @return array
* The schema definition.
*
* @see vgwort_update_20001()
*/
function _vgwort_schema_definition_20001(): array {
return [
'description' => 'Stores map from entity to job ID for registration notification.',
'fields' => [
'entity_type' => [
'type' => 'varchar_ascii',
'length' => EntityTypeInterface::ID_MAX_LENGTH,
'not null' => TRUE,
'description' => 'The entity type.',
],
'entity_id' => [
// Support string entity IDs
'type' => 'varchar_ascii',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'The entity ID.',
],
'job_id' => [
'type' => 'int',
'size' => 'big',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => 'The job ID.',
],
'success_timestamp' => [
'description' => 'The Unix timestamp when this entity was successfully post to VG Wort.',
'type' => 'int',
'size' => 'big',
'unsigned' => TRUE,
],
],
'primary key' => ['entity_type', 'entity_id'],
'indexes' => [
'job_id' => ['job_id'],
],
];
}
/**
* Create vgwort_entity_registration table.
*/
function vgwort_update_20001(): void {
// This will need to change if the schema changes.
\Drupal::database()->schema()->createTable(EntityJobMapper::TABLE, EntityJobMapper::schemaDefinition());
\Drupal::database()->schema()->createTable(EntityJobMapper::TABLE, _vgwort_schema_definition_20001());
}
/**
......@@ -60,3 +109,101 @@ function vgwort_update_20003(): void {
$config->set('entity_types', $new_entity_types)->save();
}
/**
* Create vgwort_entity_registration table.
*/
function vgwort_update_20004(): void {
$schema = \Drupal::database()->schema();
if (!$schema->fieldExists(EntityJobMapper::TABLE, 'revision_id')) {
$field_schema = [
'type' => 'int',
'not null' => FALSE,
'default' => NULL,
'description' => 'The entity revision ID of the version sent to VG Wort (if available).',
];
$schema->addField(EntityJobMapper::TABLE, 'revision_id', $field_schema);
}
if (!$schema->fieldExists(EntityJobMapper::TABLE, 'counter_id')) {
$field_schema = [
'type' => 'varchar_ascii',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'The counter ID',
];
$schema->addField(EntityJobMapper::TABLE, 'counter_id', $field_schema);
}
$schema->dropPrimaryKey(EntityJobMapper::TABLE);
$schema->addPrimaryKey(EntityJobMapper::TABLE, ['entity_type', 'entity_id', 'counter_id']);
}
/**
* Update existing rows in the vgwort_entity_registration table.
*/
function vgwort_update_20005(&$sandbox): TranslatableMarkup {
$database = \Drupal::database();
// Initialize some variables during the first pass through.
if (!isset($sandbox['total'])) {
// Get rows in the map to update
$sandbox['total'] = \Drupal::database()->select(EntityJobMapper::TABLE, 'map')
->condition('counter_id', '')
->countQuery()
->execute()
->fetchField();
$sandbox['current'] = 0;
}
// Do nothing if there's nothing to do.
if (empty($sandbox['total'])) {
$sandbox['#finished'] = 1;
return new TranslatableMarkup('@count vgwort_entity_registration rows processed.', ['@count' => $sandbox['current']]);
}
$rows_per_batch = 50;
$query = $database->select(EntityJobMapper::TABLE, 'map');
$query->fields('map', ['entity_type', 'entity_id', 'success_timestamp']);
$query->condition('counter_id', '');
$query->range(0, $rows_per_batch);
$result = $query->execute();
// Do nothing if there's nothing to do.
if (empty($result)) {
$sandbox['#finished'] = 1;
return new TranslatableMarkup('@count vgwort_entity_registration rows processed.', ['@count' => $sandbox['current']]);
}
$entity_manager = \Drupal::entityTypeManager();
foreach ($result as $row) {
$entity = $entity_manager->getStorage($row->entity_type)->load($row->entity_id);
if ($entity === NULL) {
// If the entity can not be loaded then all we can do is delete the row.
$database->delete(EntityJobMapper::TABLE)
->condition('entity_type', $row->entity_type)
->condition('entity_id', $row->entity_id)
->condition('counter_id', '')
->execute();
$sandbox['current']++;
continue;
}
// We never should be in the position where the counter ID cannot be
// determined because you cannot get in the map table if this is so but
// just in case we should set to a helpful string otherwise the query will
// fail.
$counter_id = $entity->vgwort_counter_id->value ?? 'unknown';
$revision_id = $entity instanceof RevisionableInterface && !empty($row->success_timestamp) ? $entity->getRevisionId() : NULL;
$database->update(EntityJobMapper::TABLE)
->fields([
'revision_id' => $revision_id,
'counter_id' => $counter_id,
])
->condition('entity_type', $row->entity_type)
->condition('entity_id', $row->entity_id)
->condition('counter_id', '')
->execute();
$sandbox['current']++;
}
$sandbox['#finished'] = ($sandbox['current'] / $sandbox['total']);
return new TranslatableMarkup('@count vgwort_entity_registration rows processed.', ['@count' => $sandbox['current']]);
}
......@@ -15,4 +15,4 @@ services:
arguments: ['@config.factory', '@vgwort.entity_job_mapper']
vgwort.entity_job_mapper:
class: Drupal\vgwort\EntityJobMapper
arguments: ['@database']
arguments: ['@database', '@entity_type.manager']
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment