From 4d7693a6090ba50e444a73447f488725d84a52ec Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Thu, 1 Aug 2024 15:13:49 -0300 Subject: [PATCH] Add a verifying location Drush command. --- .../VerifyIdentifierLocationCommands.php | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 src/Drush/Commands/VerifyIdentifierLocationCommands.php diff --git a/src/Drush/Commands/VerifyIdentifierLocationCommands.php b/src/Drush/Commands/VerifyIdentifierLocationCommands.php new file mode 100644 index 0000000..117bfe9 --- /dev/null +++ b/src/Drush/Commands/VerifyIdentifierLocationCommands.php @@ -0,0 +1,173 @@ +get('entity_type.manager'), + $container->get('http_client'), + $container->get('messenger'), + ); + } + + /** + * Verifies identifier target locations. + */ + #[CLI\Command(name: 'dgi_actions:verify-identifier-locations', aliases: ['da:vil'])] + #[CLI\Usage(name: 'dgi_actions:verify-identifier-locations', description: 'Verifies the target location of an identifier to ensure it matches what it is expected.')] + public function verifyIdentifierLocations(): void { + // Create a batch to find and iterate through all configured entities + // within an identifier that have the field populated. + $batch = [ + 'title' => dt('Generating identifiers...'), + 'operations' => [], + ]; + foreach ($this->entityTypeManager->getStorage('dgiactions_identifier')->loadMultiple() as $identifier) { + $batch['operations'][] = [ + [$this, 'verifyBatch'], + [ + $identifier, + ], + ]; + } + if (!empty($batch['operations'])) { + drush_op('batch_set', $batch); + drush_op('drush_backend_batch_process'); + } + else { + $this->logger()->error('No identifiers found.'); + } + + } + + /** + * Batch for updating NULL field_weight values where siblings are integers. + * + * @param \Drupal\dgi_actions\Entity\IdentifierInterface $identifier + * The DGI Actions Identifier ID to be used for the generation. + * @param array $context + * Batch context. + */ + public function verifyBatch(IdentifierInterface $identifier, &$context): void { + $sandbox =& $context['sandbox']; + $entity_type = $identifier->getEntity(); + $entity_id_key = $this->entityTypeManager->getDefinition($entity_type)->getKeys()['id']; + $entity_storage = $this->entityTypeManager->getStorage($entity_type); + $query = $entity_storage->getQuery() + ->condition($identifier->getField(), NULL, 'IS NOT NULL') + ->accessCheck(FALSE); + if (!isset($sandbox['total'])) { + $context['results'] = [ + 'failed' => [], + 'success' => [], + ]; + $count_query = clone $query; + $sandbox['total'] = $count_query->count()->execute(); + if ($sandbox['total'] === 0) { + $context['message'] = dt('Batch empty.'); + $context['finished'] = 1; + return; + } + $sandbox['last_id'] = FALSE; + $sandbox['completed'] = 0; + } + + if ($sandbox['last_id']) { + $query->condition($entity_id_key, $sandbox['last_id'], '>'); + } + $query->sort($entity_id_key); + $query->range(0, 10); + foreach ($query->execute() as $result) { + try { + $sandbox['last_id'] = $result; + $entity = $this->entityTypeManager->getStorage($entity_type)->load($result); + if (!$entity) { + $this->messenger->addError(dt('Failed to load {entity} {entity_id}; skipping.', [ + 'entity' => $entity_type, + 'entity_id' => $result, + ])); + continue; + } + $identifier_location = $entity->get($identifier->getField())->getString(); + $response = $this->httpClient->request('HEAD', $identifier_location, [ + 'allow_redirects' => FALSE, + ]); + $location = $response->getHeaderLine('Location'); + $expected_location = FALSE; + + /** @var \Drupal\context\Entity\Context $context_entity */ + foreach ($this->entityTypeManager->getStorage('context')->loadMultiple() as $context_entity) { + if ($context_entity->hasCondition('dgi_actions_entity_persistent_identifier_populated') || $context_entity->hasReaction('dgi_actions_entity_mint_reaction')) { + $reaction = $context_entity->getReaction('dgi_actions_entity_mint_reaction'); + $config = $reaction->getConfiguration(); + $action_ids = $config['actions']; + $action = reset($action_ids); + + /** @var \Drupal\dgi_actions\Plugin\Action\MintIdentifier $action_entity */ + $action_entity = $this->entityTypeManager->getStorage('action')->load($action)->getPlugin(); + // Ensure this action corresponds to this identifier before + // anything else. + if ($action_entity->getIdentifier()->id() !== $identifier->id()) { + continue; + } + $action_entity->setEntity($entity); + $expected_location = $action_entity->getExternalUrl(); + } + } + if ($location !== $expected_location) { + $this->messenger->addError(dt('Entity {entity} {entity_id} has a location mismatch. Expected: {expected}, Actual: {actual}', [ + 'entity' => $entity_type, + 'entity_id' => $result, + 'expected' => $expected_location, + 'actual' => $location, + ])); + } + } + catch (\Exception $e) { + $this->messenger->addError(dt('Encountered an exception: {exception}', [ + 'exception' => $e, + ])); + } + $sandbox['completed']++; + $context['finished'] = $sandbox['completed'] / $sandbox['total']; + } + } + +}