Skip to content

Commit

Permalink
Walk back approach: Keep config entities, but use core API to suppress.
Browse files Browse the repository at this point in the history
The approach with content entities got into issue due to varying
identifiers in the derived `migrate_plus` entities that would have to be
updated, as rederiving from the migrations-in-code could drift from what
the old `migrate_plus` entities described.

Given the issue is really that we want to prevent these entities from
hitting config imports/exports, and we needed a solution for it for the
`migrate_plus` entities in any case, it seems easiest just to keep the
request entities as config entities for now. If/when we rework away from
`migrate_plus` and `migrate_tools` for GUI, and have some lifecycle
expectations baked in around request entities, it might make sense to
revisit.
  • Loading branch information
adam-vessey committed Jul 25, 2024
1 parent fbe14ac commit 98fbe28
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 470 deletions.
63 changes: 63 additions & 0 deletions config/schema/islandora_spreadsheet_ingest.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,66 @@ islandora_spreadsheet_ingest.settings:
label: 'Allowed source URI schemes.'
sequence:
type: string

islandora_spreadsheet_ingest.request.*:
type: config_entity
mapping:
id:
type: string
label: ID
label:
type: label
label: Label
active:
type: boolean
label: Active
description: If this request should have migrations derived for it.
sheet:
type: mapping
mapping:
file:
# XXX: Really... kind of indicative that these should be pulled out
# to content entities instead of being config entities... the whole
# having-to-reference a file thing... because the "entity:file"
# thing does not appear to work...
#type: entity:file
type: ignore
label: The spreadsheet file to process.
sheet:
type: string
label: The worksheet of the file to process.
mappings:
type: islandora_spreadsheet_ingest.migration_structure
owner:
# XXX: Further reinforcement that these should be pulled out to content
# entities instead of config, because we are relating to the user here.
#type: entity:user
type: ignore
label: The owner's ID; should be either an int or a string.
originalMapping:
type: string
label: |
Reference to the original mapping from which this request was derived.
islandora_spreadsheet_ingest.migration_structure:
type: mapping
mapping:
original_migration_id:
type: string
label: ID
mappings:
type: sequence
sequence:
type: mapping
mapping:
weight:
type: integer
pipeline:
type: sequence
sequence:
# XXX: The migrate plugin does not define schemas for its plugins,
# nor any obvious mechanism by which to make reference to them...
# migrate_plus _does_ roll a handful, describing the things from
# migrate; however, it is not complete, nor necessarily desirable.
# ... so let's just ignore, for now at least.
type: ignore
132 changes: 23 additions & 109 deletions islandora_spreadsheet_ingest.install
Original file line number Diff line number Diff line change
Expand Up @@ -5,121 +5,35 @@
* Installation hooks.
*/

use Drupal\Core\Entity\ContentEntityType;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\islandora_spreadsheet_ingest\Entity\Request;

/**
* Implements hook_update_last_removed().
* Drop old, disused tables.
*/
function islandora_spreadsheet_ingest_update_last_removed() : int {
return 9001;
function islandora_spreadsheet_ingest_update_8201() {
$schema = \Drupal::service('database')->schema();

$tables = [
'islandora_spreadsheet_ingest_templates',
'islandora_spreadsheet_ingest_ingests',
];
array_map([$schema, 'dropTable'], $tables);

return t('Dropped tables.');
}

/**
* Replace config entity with content entity.
* Ensure the Islandora Spreadsheet Request ConfigEntityType is installed.
*/
function islandora_spreadsheet_ingest_update_9002() : void {
function islandora_spreadsheet_ingest_update_9001() {
$upm = \Drupal::entityDefinitionUpdateManager();
$ent = $upm->getEntityType('isi_request');
if (is_null($ent)) {
$upm->installEntityType(\Drupal::entityTypeManager()
->getDefinition('isi_request')
);

$upm->uninstallEntityType($upm->getEntityType('isi_request'));

// Much like general schema updates, this needs to include the definition
// inline to be installed, including field definitions, instead of dynamically
// lifting the definitions from the entity type manager in order to be able to
// reliably apply future updates.
$definition = new ContentEntityType([
"id" => "isi_request",
"label" => \t("Islandora Spreadsheet Ingest Request"),
"handlers" => [
"storage_schema" => "Drupal\islandora_spreadsheet_ingest\RequestStorageSchema",
"list_builder" => "Drupal\islandora_spreadsheet_ingest\Controller\RequestListBuilder",
"form" => [
"process" => "Drupal\islandora_spreadsheet_ingest\Form\Ingest\Review",
"add" => "Drupal\islandora_spreadsheet_ingest\Form\Ingest\FileUpload",
"delete" => "Drupal\islandora_spreadsheet_ingest\Form\RequestDeleteForm",
"edit" => "Drupal\islandora_spreadsheet_ingest\Form\Ingest\FileUpload",
"view" => "Drupal\islandora_spreadsheet_ingest\Form\Ingest\Review",
],
"access" => "Drupal\islandora_spreadsheet_ingest\RequestAccessControlHandler",
"view_builder" => "Drupal\islandora_spreadsheet_ingest\RequestViewBuilder",
],
"admin_permission" => "administer islandora_spreadsheet_ingest requests",
"base_table" => "islandora_spreadsheet_ingest_request",
"entity_keys" => [
"id" => "id",
"uuid" => "uuid",
"label" => "label",
"owner" => "uid",
],
"links" => [
"canonical" => "/admin/content/islandora_spreadsheet_ingest/{isi_request}",
"process-form" => "/admin/content/islandora_spreadsheet_ingest/{isi_request}/process",
"edit-form" => "/admin/content/islandora_spreadsheet_ingest/{isi_request}/edit",
"map-form" => "/admin/content/islandora_spreadsheet_ingest/{isi_request}/mapping",
"delete-form" => "/admin/content/islandora_spreadsheet_ingest/{isi_request}/delete",
],
]);
$fields = [];
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(\t('User ID'))
->setSetting('target_type', 'user')
->setTranslatable(FALSE)
->setDefaultValueCallback(Request::class . '::getDefaultEntityOwner');
$fields['label'] = BaseFieldDefinition::create('string')
->setLabel(\t('Title'))
->setRequired(TRUE)
->setTranslatable(FALSE)
->setRevisionable(FALSE)
->setSetting('max_length', 255)
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'string',
'weight' => -5,
])
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => -5,
])
->setDisplayConfigurable('form', TRUE)
->setCardinality(1);
$fields['machine_name'] = BaseFieldDefinition::create('string')
->setLabel(\t('Machine Name'))
->setRequired(TRUE)
->setTranslatable(FALSE)
->setRevisionable(FALSE)
->setCardinality(1)
->addConstraint('UniqueField', [
'message' => 'The machine_name %value is already in use.',
]);
$fields['active'] = BaseFieldDefinition::create('boolean')
->setLabel(\t('Label'))
->setRequired(TRUE)
->setCardinality(1)
->setTranslatable(FALSE)
->setRevisionable(FALSE);
$fields['sheet_file'] = BaseFieldDefinition::create('entity_reference')
->setLabel(\t('Spreadsheet file'))
->setRequired(TRUE)
->setTranslatable(FALSE)
->setRevisionable(FALSE)
->setSetting('target_type', 'file')
->setDisplayOptions('form', [
'type' => 'file_generic',
])
->setCardinality(1);
$fields['sheet_sheet'] = BaseFieldDefinition::create('string')
->setLabel(\t('Worksheet'))
->setDescription(\t('The specific worksheet if the file corresponds to an ODS/XLSX which is possible of containing multiple.'))
->setCardinality(1);
$fields['mappings'] = BaseFieldDefinition::create('map')
->setLabel(\t('Mappings'))
->setDescription(\t('Migration mappings'))
->setCardinality(1);
$fields['original_mapping'] = BaseFieldDefinition::create('string')
->setLabel(\t('Original mapping'))
->setDescription(\t('Original migration template'))
->setCardinality(1);

$upm->installFieldableEntityType($definition, $fields);
return t('The "isi_request" config entity has been installed.');
}
else {
return t('The "isi_request" config entity is already installed.');
}
}
125 changes: 0 additions & 125 deletions islandora_spreadsheet_ingest.post_update.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,131 +5,6 @@
* Post-update hooks.
*/

use Drupal\Core\Utility\UpdateException;
use Drupal\migrate\Plugin\migrate\id_map\Sql;

/**
* Migrate request entities from config to content.
*/
function islandora_spreadsheet_ingest_post_update_migrate_requests_from_config_to_content_0(array &$sandbox) {
$config_factory = \Drupal::configFactory();
if (!isset($sandbox['count'])) {
$sandbox['names'] = $config_factory->listAll('islandora_spreadsheet_ingest.request');
$sandbox['count'] = count($sandbox['names']);
if ($sandbox['count'] === 0) {
return "No entities to migrate.";
}
$sandbox['current'] = 0;
}

if (!($current = array_pop($sandbox['names']))) {
throw new UpdateException("Unexpectedly failed to get item from array.");
}

// Create copy of request.
$config = $config_factory->get($current);
/** @var \Drupal\islandora_spreadsheet_ingest\RequestInterface $request */
$request = \Drupal::entityTypeManager()->getStorage('isi_request')->create([
'label' => $config->get('label'),
'machine_name' => $config->get('id'),
'sheet_file' => $config->get('sheet')['file'],
'sheet_sheet' => $config->get('sheet')['sheet'],
'mappings' => $config->get('mappings'),
'original_mapping' => $config->get('originalMapping'),
'owner' => $config->get('owner'),
'active' => $config->get('active'),
]);
$request->save();

// Copy ID map and messages tables to the new entities, as those
// associated with the old should be deleted in the next phase.
$source_mg_name = "isi__{$config->get('id')}";
$dest_mg_name = \Drupal::service('islandora_spreadsheet_ingest.migration_group_deriver')->deriveName($request);
/** @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager */
$migration_plugin_manager = \Drupal::service('plugin.manager.migration');
foreach (array_keys($request->getMappings()) as $name) {
$source_migration_id = "{$source_mg_name}_{$name}";
$dest_migration_id = "{$dest_mg_name}_{$name}";
/** @var \Drupal\migrate\Plugin\MigrationInterface $source_migration */
$source_migration = $migration_plugin_manager->createInstance($source_migration_id);
/** @var \Drupal\migrate\Plugin\MigrationInterface $dest_migration */
$dest_migration = $migration_plugin_manager->createInstance($dest_migration_id);
$source_id_map = $source_migration->getIdMap();
$dest_id_map = $dest_migration->getIdMap();
if (!($source_id_map instanceof Sql)) {
continue;
}
if (!($dest_id_map instanceof Sql)) {
continue;
}

// XXX: Calling Sql::getDatabase() presently initializes things, to ensure
// that the relevant tables exist.
$source_id_map->getDatabase();
$database = $dest_id_map->getDatabase();

$database->insert($dest_id_map->mapTableName())
->from(
$database->select($source_id_map->mapTableName(), 'm')
->fields('m')
)
->execute();
$database->insert($dest_id_map->messageTableName())
->from(
$database->select($source_id_map->messageTableName(), 'm')
->fields('m')
)
->execute();
}

$sandbox['#finished'] = ++$sandbox['current'] / $sandbox['count'];
}

/**
* Delete disused request config entities.
*/
function islandora_spreadsheet_ingest_post_update_migrate_requests_from_config_to_content_1(array &$sandbox) {
$config_factory = \Drupal::configFactory();
if (!isset($sandbox['count'])) {
$sandbox['names'] = $config_factory->listAll('islandora_spreadsheet_ingest.request');
$sandbox['count'] = count($sandbox['names']);
if ($sandbox['count'] === 0) {
return "No entities to delete.";
}
$sandbox['current'] = 0;
}

if (!($current = array_pop($sandbox['names']))) {
throw new UpdateException("Unexpectedly failed to get item from array.");
}

$config = $config_factory->getEditable($current);

$file_usage_service = \Drupal::service('file.usage');
$file_service = \Drupal::service('entity_type.manager')->getStorage('file');
$fids = $config->get('sheet')['file'];
if ($fids && ($file = $file_service->load(reset($fids)))) {
$file_usage_service->delete(
$file,
'islandora_spreadsheet_ingest',
'isi_request',
$config->get('id'),
);
}
$source_mg_name = "isi__{$config->get('id')}";
/** @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager */
$migration_plugin_manager = \Drupal::service('plugin.manager.migration');
foreach (array_keys($config->get('mappings')) as $name) {
$source_migration_id = "{$source_mg_name}_{$name}";
/** @var \Drupal\migrate\Plugin\MigrationInterface $source_migration */
$source_migration = $migration_plugin_manager->createInstance($source_migration_id);
$source_migration->getIdMap()->destroy();
}

$config->delete();
$sandbox['#finished'] = ++$sandbox['current'] / $sandbox['count'];
}

/**
* Set a value for islandora_spreadsheet_ingest.settings:schemes, if unset.
*/
Expand Down
16 changes: 0 additions & 16 deletions islandora_spreadsheet_ingest.routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,26 @@ entity.isi_request.edit_form:
_entity_form: 'isi_request.edit'
requirements:
_entity_access: 'isi_request.update'
options:
parameters:
isi_request:
type: islandora_spreadsheet_ingest_request
entity.isi_request.delete_form:
path: '/admin/content/islandora_spreadsheet_ingest/{isi_request}/delete'
defaults:
_title: 'Delete'
_entity_form: 'isi_request.delete'
requirements:
_entity_access: 'isi_request.delete'
options:
parameters:
isi_request:
type: islandora_spreadsheet_ingest_request
entity.isi_request.canonical:
path: '/admin/content/islandora_spreadsheet_ingest/{isi_request}'
defaults:
_entity_view: 'isi_request.full'
requirements:
_entity_access: 'isi_request.view'
options:
parameters:
isi_request:
type: islandora_spreadsheet_ingest_request
entity.isi_request.process_form:
path: '/admin/content/islandora_spreadsheet_ingest/{isi_request}/process'
defaults:
_title: 'Process'
_entity_form: 'isi_request.process'
requirements:
_entity_access: 'isi_request.activate'
options:
parameters:
isi_request:
type: islandora_spreadsheet_ingest_request
islandora_spreadsheet_ingest.admin:
path: '/admin/config/islandora_spreadsheet_ingest'
defaults:
Expand Down
Loading

0 comments on commit 98fbe28

Please sign in to comment.