archivesspace-8.x-1.x-dev/src/Plugin/rest/resource/UpdateASResource.php
src/Plugin/rest/resource/UpdateASResource.php
<?php
namespace Drupal\archivesspace\Plugin\rest\resource;
use Drupal\archivesspace\ArchivesSpaceSession;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\MigrateMessage;
use Drupal\migrate\Plugin\Migration;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
/**
* Provides an update endpoint for ArchivesSpace.
*
* @RestResource(
* id = "update_archivesspace_resource",
* label = @Translation("Update ArchivesSpace resource"),
* uri_paths = {
* "canonical" = "/archivesspace/update/{id}"
* }
* )
*/
class UpdateASResource extends ResourceBase {
/**
* Responds to entity GET requests.
*
* @param string $id
* The resource id to update.
*
* @return \Drupal\rest\ResourceResponse
* HTTP Response.
*
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
* Thrown when no log entry was provided.
*/
public function get($id) {
$archives = new ArchivesSpaceSession();
$response = $archives->request('GET', '/search', [
'q' => $id,
'fields[]' => 'identifier,uri',
'type[]' => 'resource',
'page' => '1',
'page_size' => '1',
]);
$result = $response['results'][0];
if ($result['identifier'] !== $id) {
throw new BadRequestHttpException('No ArchivesSpace resource was found for ' . $id);
}
$result2 = $archives->request('GET', $result["uri"] . "/tree");
$uris = $this->getChildrenUris($result2);
$this->utils = \Drupal::service('archivesspace.utils');
$context = ['results' => []];
$this->updateResource(1, $archives, $uris, $context);
$this->updateResourceFinished(TRUE, $context['results'], []);
$response = "success";
return (new ResourceResponse($response))->addCacheableDependency([
'#cache' => [
'max-age' => 0,
],
]);
}
/**
* Helper function to build a list of object uris from a tree.
*
* @param array $node
* Batch ID.
*
* @return array
* list of object URIs.
*/
private function getChildrenUris(array $node) {
$ans = [$node['record_uri']];
foreach ($node['children'] as $child) {
$ans = array_merge($ans, $this->getChildrenUris($child));
}
return $ans;
}
/**
* Batch process callback.
*
* @param int $id
* Batch ID.
* @param \Drupal\archivesspace\ArchivesSpaceSession $session
* Details of the operation.
* @param array $parameters
* The operations' parameters.
* @param object $context
* Context for operations.
*/
public function updateResource($id, ArchivesSpaceSession $session, array $parameters, &$context) {
// Get page number and query from operation details.
// Issue query.
// Group embedded data rows into migrations based on each's json_model.
$migrations = [];
foreach ($parameters as $uri) {
$result = $session->request('GET', $uri);
$context['message'] = "Processing resource.";
if ($migration_id = $this->utils->getUriMigration($result['uri'])) {
$migrations[$migration_id][] = $result;
}
}
foreach ($migrations as $migration_id => $data) {
$context['message'] = $this->t("Running migration '@migration' with @rows items.", [
'@migration' => $migration_id,
'@rows' => count($data),
]);
// Load the relevant migration with the embedded data source.
$migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id, [
'source' => [
'plugin' => 'embedded_data',
'data_rows' => $data,
'ids' => ['uri' => ['type' => 'string']],
],
]);
if (!$migration) {
$context['message'] = $this->t("Could not find a migration with the ID '@id'!", ['@id' => $migration_id]);
return;
}
if ($migration->getStatus() != Migration::STATUS_IDLE) {
$migration->setStatus(Migration::STATUS_IDLE);
}
// Force the migration for batches rather than fail
// due to missed requirements.
$migration->set('requirements', []);
$migration->getIdMap()->prepareUpdate();
$executable = new MigrateExecutable($migration, new MigrateMessage());
$migration_result = $executable->import();
if ($migration_result == MigrationInterface::RESULT_COMPLETED) {
if (!array_key_exists('migration_counts', $context['results'])) {
$context['results']['migration_counts'] = [];
}
if (!array_key_exists($migration_id, $context['results']['migration_counts'])) {
$context['results']['migration_counts'][$migration_id] = 0;
}
$context['results']['migration_counts'][$migration_id] += count($data);
}
else {
$result_msg = '';
switch ($migration_result) {
// Error messages pulled from the MigrationInterface API docs.
case MigrationInterface::RESULT_DISABLED:
$result_msg = "This migration is disabled, skipping.";
break;
case MigrationInterface::RESULT_FAILED:
$result_msg = "The process had a fatal error.";
break;
case MigrationInterface::RESULT_INCOMPLETE:
$result_msg = "The process has stopped itself (e.g., the memory limit is approaching).";
break;
case MigrationInterface::RESULT_SKIPPED:
$result_msg = "Dependencies are unfulfilled - skip the process.";
break;
case MigrationInterface::RESULT_STOPPED:
$result_msg = "The process was stopped externally (e.g., via drush migrate-stop).";
break;
}
// Kill further processing.
throw new \Exception("Migration $migration_id from page {$results['this_page']} failed to complete with the message: $result_msg");
}
}
}
/**
* Batch finished callback.
*
* @param bool $success
* Success of the operation.
* @param array $results
* Array of results for post processing.
* @param array $operations
* Array of operations.
*/
public function updateResourceFinished($success, array $results, array $operations) {
if ($success) {
// Report out migrations.
if (!empty($results['migration_counts'])) {
foreach ($results['migration_counts'] as $mid => $count) {
\Drupal::messenger()->addMessage($this->t("Migration @mid processed @count items.", [
'@mid' => $mid,
'@count' => $count,
]));
}
}
else {
\Drupal::messenger()->addMessage($this->t("Warning: no migrations appear to have been run."));
}
}
else {
// An error occurred.
// $operations contains the operations that remained unprocessed.
$error_operation = reset($operations);
\Drupal::messenger()->addMessage(
$this->t('An error occurred while processing @operation with arguments : @args',
[
'@operation' => 'Update Page',
'@args' => print_r($error_operation[1][2], TRUE),
]
)
);
}
}
}
