From 37e75387f5dd41deca0bcb49a6e57a7429b36924 Mon Sep 17 00:00:00 2001 From: Chris MacDonald <31731869+chrismacdonaldw@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:26:45 -0300 Subject: [PATCH 01/22] Add new fields to FOXML migration --- .../migrations/dgis_nodes.yml | 481 +++++++++++++++++- 1 file changed, 480 insertions(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index eb204d12..52fc1f77 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -334,7 +334,7 @@ process: property: nodeValue field_description: - << : *base_mods_node - query: 'mods:abstract' + query: 'mods:abstract[@displayLabel="summary"]' - plugin: callback callable: iterator_to_array - plugin: multiple_values @@ -1693,6 +1693,36 @@ process: - plugin: callback callable: array_filter - plugin: null_coalesce + field_related_item_identifier: + - <<: *nested_mods_node + query: 'mods:relatedItem/mods:identifier' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_related_item_genre: + - <<: *nested_mods_node + query: 'mods:relatedItem/mods:genre' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: genre + <<: *generic_term_after + - <<: *generic_term_extract _resource_type: - << : *base_mods_node query: 'mods:typeOfResource' @@ -1973,6 +2003,455 @@ process: default_value: language <<: *generic_term_after - <<: *generic_term_extract + field_degree_name: + - <<: *base_mods_node + query: 'mods:extension/etd:degree/etd:name' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: degree_names + <<: *generic_term_after + - <<: *generic_term_extract + _degree_level: + - <<: *base_mods_node + query: 'mods:extension/etd:degree/etd:level' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + field_degree_level: + - plugin: default_value + source: '@_degree_level' + default_value: Unspecified + - plugin: entity_generate + bundle: degree_levels + bundle_key: vid + entity_type: taxonomy_term + value_key: name + ignore_case: *case_insensitive + field_department: + - <<: *base_mods_node + query: 'mods:extension/etd:degree/etd:discipline' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: discipline + <<: *generic_term_after + - <<: *generic_term_extract + field_institution: + - <<: *base_mods_node + query: 'mods:extension/etd:degree/etd:grantor' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: institution + <<: *generic_term_after + - <<: *generic_term_extract + field_version_identifier: + - <<: *base_mods_node + query: 'mods:note[@type="version identification"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_abstract: + - <<: *base_mods_node + query: 'mods:abstract[@displayLabel="academic"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_open_url: + - <<: *base_mods_node + query: 'mods:identifier[@type="openurl"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_ismn: + - <<: *base_mods_node + query: 'mods:identifier[@type="ismn"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_repec: + - <<: *base_mods_node + query: 'mods:identifier[@type="repec"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_gpo_number: + - <<: *base_mods_node + query: 'mods:identifier[@type="gpo"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_pubmed_central_number: + - <<: *base_mods_node + query: 'mods:identifier[@type="pmcid"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_pubmed_number: + - <<: *base_mods_node + query: 'mods:identifier[@type="pmid"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_ddc_classification: + - <<: *base_mods_node + query: 'mods:classification[@authority="ddc"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_sudoc_number: + - <<: *base_mods_node + query: 'mods:classification[@authority="sudoc"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_swank_classification: + - <<: *base_mods_node + query: 'mods:classification[@authority="swank"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: null_coalesce + field_conference: + - <<: *base_mods_node + query: 'mods:name[@type="conference"]/mods:namePart' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: conference_events + <<: *generic_term_after + - <<: *generic_term_extract + field_series_paragraph: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="series"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_paragraph_generate + validate: *validate + type: series + process_values: true + values: + field_series_titles: + - <<: *nested_mods_node + query: 'mods:titleInfo/mods:title' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: series_titles + <<: *generic_term_after + - <<: *generic_term_extract + field_series_number: + - <<: *nested_mods_node + query: 'mods:titleInfo/mods:partNumber' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_title: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:titleInfo/mods:title' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: titles + <<: *generic_term_after + - <<: *generic_term_extract + field_publication_number: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:titleInfo/mods:partNumber' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_volume_title: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:titleInfo/mods:partName' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_chapter_number: + - <<: *base_mods_node + query: 'mods:part[@type="chapter"]/mods:detail/mods:number' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_section: + - <<: *base_mods_node + query: 'mods:part[@type="section"]/mods:detail/mods:title' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_identifier: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:identifier' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_url: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:location/mods:url' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: callback + callable: trim + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_publication_genre: + - <<: *base_mods_node + query: 'mods:relatedItem[@type="host"]/mods:genre' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: genre + <<: *generic_term_after + - <<: *generic_term_extract + field_extent_total_pages: + - <<: *base_mods_node + query: 'mods:part/mods:extent/mods:total' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_extent_first_page: + - <<: *base_mods_node + query: 'mods:part/mods:extent/mods:start' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_extent_last_page: + - <<: *base_mods_node + query: 'mods:part/mods:extent/mods:end' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_admin_note: + - <<: *base_mods_node + query: 'mods:note[@type="admin"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + field_funder: + - <<: *base_mods_node + query: 'mods:role/mods:roleTerm="funder"' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: funders + <<: *generic_term_after + - <<: *generic_term_extract + field_sponsorship_information: + - <<: *base_mods_node + query: 'mods:note[@type="funding"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + _use_license: + - <<: *base_mods_node + query: 'mods:accessCondition[@type="use and reproduction"][@displayLabe="Creative Commons"]' + - plugin: callback + callable: iterator_to_array + - plugin: multiple_values + - plugin: dgi_migrate.subproperty + property: nodeValue + - plugin: single_value + - plugin: callback + callable: array_filter + field_use_license: + - plugin: default_value + source: '@_use_license' + default_value: Unspecified + - plugin: entity_generate + bundle: creative_commons_licenses_4_0 + bundle_key: vid + entity_type: taxonomy_term + value_key: name + ignore_case: *case_insensitive nid: - plugin: migration_lookup source: '@field_pid' From 1571a041ead1c8cd54eb58453b7ed45dbf77dfcc Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 26 Jul 2024 11:51:18 -0300 Subject: [PATCH 02/22] Related item things are operating inside of the element context already. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 52fc1f77..b384afb2 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1695,7 +1695,7 @@ process: - plugin: null_coalesce field_related_item_identifier: - <<: *nested_mods_node - query: 'mods:relatedItem/mods:identifier' + query: 'mods:identifier' - plugin: callback callable: iterator_to_array - plugin: multiple_values @@ -1709,7 +1709,7 @@ process: - plugin: null_coalesce field_related_item_genre: - <<: *nested_mods_node - query: 'mods:relatedItem/mods:genre' + query: 'mods:genre' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty From 0ffff687492e613fc6e23957012cba66eb32cfa8 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 26 Jul 2024 13:45:12 -0300 Subject: [PATCH 03/22] Fix some inline code docs. Also, change in the invocation recommended by Extended Analysis. --- src/Plugin/migrate/process/Xml/ContextQuery.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Plugin/migrate/process/Xml/ContextQuery.php b/src/Plugin/migrate/process/Xml/ContextQuery.php index 4d825cfa..fa78efd7 100644 --- a/src/Plugin/migrate/process/Xml/ContextQuery.php +++ b/src/Plugin/migrate/process/Xml/ContextQuery.php @@ -27,11 +27,11 @@ class ContextQuery extends ProcessPluginBase { use MissingBehaviorTrait; /** - * The instance on which to run the query. + * Reference to the instance in the row on which to run the query. * - * @var \DOMXPath + * @var string */ - protected mixed $xpath; + protected string $xpath; /** * The query to execute. @@ -84,7 +84,7 @@ public function transform($value, MigrateExecutableInterface $migrate_executable ])); } - return call_user_func([$xpath, $this->method], $this->query, $value); + return $xpath->{$this->method}($this->query, $value); } } From c813fd17d4e79b6a73116fd9d79fc79eb45c21fa Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 26 Jul 2024 13:46:10 -0300 Subject: [PATCH 04/22] Allow the passthrough of the `_mods_xpath` instance. --- .../migrations/dgis_nodes.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index b384afb2..86f0fb18 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1638,6 +1638,10 @@ process: type: related_item process_values: true values: + _mods_xpath: + # XXX: Copy here so it's available for further subprocessing. + - plugin: get + source: parent_row/dest/_mods_xpath field_relationship_type: - << : *nested_mods_node query: '@type' @@ -2209,6 +2213,10 @@ process: type: series process_values: true values: + _mods_xpath: + # XXX: Copy here so it's available for further subprocessing. + - plugin: get + source: parent_row/dest/_mods_xpath field_series_titles: - <<: *nested_mods_node query: 'mods:titleInfo/mods:title' @@ -2405,7 +2413,7 @@ process: - plugin: null_coalesce field_funder: - <<: *base_mods_node - query: 'mods:role/mods:roleTerm="funder"' + query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"]/mods:namePart' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty From 4934fe2a57b3b040fc1d0d993a984a12e0dd1cd7 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 26 Jul 2024 15:39:41 -0300 Subject: [PATCH 05/22] Format chain of exceptions to facilitate debugging. Also, prevent whatever was causing the serialization issue? Was apparently related to the "sub process" plugin naively rethrowing exceptions as `\Exception`, which would've proceeded with an undefined `$save` variable? --- src/MigrateBatchExecutable.php | 39 +++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/MigrateBatchExecutable.php b/src/MigrateBatchExecutable.php index 9344dc6d..eb23c5b5 100644 --- a/src/MigrateBatchExecutable.php +++ b/src/MigrateBatchExecutable.php @@ -237,6 +237,30 @@ protected function enqueue() { return MigrationInterface::RESULT_COMPLETED; } + /** + * Helper to format exceptions. + * + * @param \Exception $e + * The exception to format. + * @param string $prefix + * Prefix to tack onto exceptions, such that causes can be added + * recursively. + * @param int $depth + * Recursive depth, to augment message. + * + * @return string + * The formatted exception. + */ + protected function formatException(\Throwable $e, string $prefix = 'Initial', int $depth = 0) : string { + $parts = []; + $parts[] = "$prefix message: {$e->getMessage()}"; + $parts[] = "$prefix trace:\n{$e->getTraceAsString()}"; + if ($e->getPrevious()) { + $parts[] = $this->formatException($e->getPrevious(), "--- Cause #{$depth}", $depth + 1); + } + return implode("\n", $parts); + } + /** * The meat of processing a row. * @@ -257,11 +281,6 @@ protected function processRowFromQueue(Row $row) { $this->processRow($row); $save = TRUE; } - catch (MigrateException $e) { - $this->getIdMap()->saveIdMapping($row, [], $e->getStatus()); - $this->saveMessage($e->getMessage(), $e->getLevel()); - $save = FALSE; - } catch (MigrateSkipRowException $e) { if ($e->getSaveToMap()) { $id_map->saveIdMapping($row, [], MigrateIdMapInterface::STATUS_IGNORED); @@ -271,6 +290,16 @@ protected function processRowFromQueue(Row $row) { } $save = FALSE; } + catch (MigrateException $e) { + $this->getIdMap()->saveIdMapping($row, [], $e->getStatus()); + $this->saveMessage($this->formatException($e), $e->getLevel()); + $save = FALSE; + } + catch (\Exception $e) { + $this->getIdMap()->saveIdMapping($row, [], MigrateIdMapInterface::STATUS_FAILED); + $this->saveMessage($this->formatException($e), MigrationInterface::MESSAGE_ERROR); + $save = FALSE; + } if ($save) { try { From 0adcd858853c71a19cfbee2bb96d4d442f4c0899 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 10:56:36 -0300 Subject: [PATCH 06/22] Pull subject apart, and something theoretical for "funders". --- .../migrations/dgis_nodes.yml | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 86f0fb18..466817b4 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1779,7 +1779,7 @@ process: - plugin: multiple_values - plugin: dgi_migrate.subproperty property: nodeValue - _subject_topic: + field_subject: - << : *base_mods_node query: 'mods:subject/mods:topic[normalize-space()]' - plugin: callback @@ -1795,7 +1795,7 @@ process: default_value: subject <<: *generic_term_after - <<: *generic_term_extract - _subject_name_personal: + field_subject_name_person: - << : *base_mods_node query: 'mods:subject/mods:name[@type="personal" or not(@type)][normalize-space()]' - plugin: callback @@ -1866,7 +1866,7 @@ process: method: row - plugin: dgi_migrate.process.single_extract index: [ target_id ] - _subject_name_corporate: + field_subject_name_organization: - << : *base_mods_node query: 'mods:subject/mods:name[@type="corporate"][normalize-space()]' - plugin: callback @@ -1927,13 +1927,6 @@ process: method: row - plugin: dgi_migrate.process.single_extract index: [ target_id ] - field_subject: - - plugin: get - source: - - '@_subject_topic' - - '@_subject_name_personal' - - '@_subject_name_corporate' - - plugin: flatten field_sub_location: - << : *base_mods_node query: 'mods:location/mods:holdingSimple/mods:copyInformation/mods:subLocation' @@ -2413,7 +2406,7 @@ process: - plugin: null_coalesce field_funder: - <<: *base_mods_node - query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"]/mods:namePart' + query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"][normalize-space(mods:namePart)]' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty @@ -2425,7 +2418,31 @@ process: _vid: - plugin: default_value default_value: funders - <<: *generic_term_after + _auth_value_uri: + - <<: *nested_mods_node + query: 'string(@valueURI)' + method: evaluate + _auth_source: + - <<: *nested_mods_node + query: 'string(@authority)' + method: evaluate + _value: + - <<: *nested_mods_node + query: 'normalize-space(mods:namePart)' + method: evaluate + actual: + - plugin: get + source: + - '@_auth_source' + - '@_auth_value_uri' + - '@_value' + # XXX: Needs to be provided wherever this is used, corresponding + # to the vocab in which to do the things. + - '@_vid' + - plugin: flatten + - plugin: migration_lookup + migration: dgis_stub_terms_generic + stub_id: dgis_stub_terms_generic - <<: *generic_term_extract field_sponsorship_information: - <<: *base_mods_node From 8a09a33fd1fe45a3a7f33a4180997ecf6f8f8a20 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 11:18:05 -0300 Subject: [PATCH 07/22] Update `field_funders`. --- .../migrations/dgis_nodes.yml | 67 ++++++++++++------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 466817b4..b6b28e03 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -2405,7 +2405,7 @@ process: callable: array_filter - plugin: null_coalesce field_funder: - - <<: *base_mods_node + - << : *base_mods_node query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"][normalize-space(mods:namePart)]' - plugin: callback callable: iterator_to_array @@ -2415,35 +2415,56 @@ process: - plugin: dgi_migrate.sub_process process_values: true values: - _vid: - - plugin: default_value - default_value: funders - _auth_value_uri: - - <<: *nested_mods_node - query: 'string(@valueURI)' + _authority: + - << : *nested_mods_node + query: 'normalize-space(@authority)' method: evaluate - _auth_source: - - <<: *nested_mods_node - query: 'string(@authority)' + _value_uri: + - << : *nested_mods_node + query: 'normalize-space(@valueURI)' method: evaluate - _value: - - <<: *nested_mods_node - query: 'normalize-space(mods:namePart)' + _date_name: + - << : *nested_mods_node + query: 'normalize-space(mods:namePart[@type="date"][normalize-space()][1])' method: evaluate - actual: + _display_form: + - << : *nested_mods_node + query: 'normalize-space(mods:displayForm[normalize-space()][1])' + method: evaluate + _untyped_names: + - << : *nested_mods_node + query: 'normalize-space(mods:namePart[not(@type)][normalize-space()])' + method: evaluate + _affiliation_lookup: + - << : *nested_mods_node + query: 'normalize-space(mods:affiliation[normalize-space()])' + method: evaluate + - plugin: skip_on_empty + method: process + - plugin: migration_lookup + migration: dgis_stub_terms_affiliate + stub_id: dgis_stub_terms_affiliate + _affiliation: + - plugin: default_value + source: '@_affiliation_lookup' + default_value: '' + target_id: - plugin: get source: - - '@_auth_source' - - '@_auth_value_uri' - - '@_value' - # XXX: Needs to be provided wherever this is used, corresponding - # to the vocab in which to do the things. - - '@_vid' + - '@_authority' + - '@_value_uri' + - '@_untyped_names' + - '@_date_name' + - '@_display_form' + - '@_affiliation' - plugin: flatten - plugin: migration_lookup - migration: dgis_stub_terms_generic - stub_id: dgis_stub_terms_generic - - <<: *generic_term_extract + migration: dgis_stub_terms_corporate_body + stub_id: dgis_stub_terms_corporate_body + - plugin: skip_on_empty + method: row + - plugin: dgi_migrate.process.single_extract + index: [ target_id ] field_sponsorship_information: - <<: *base_mods_node query: 'mods:note[@type="funding"]' From b8e254941a6f9be86c2921f5a7b08a8e36804f5c Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 11:25:37 -0300 Subject: [PATCH 08/22] Fix typo in `displayLabel` attribute XPath. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index b6b28e03..c102c83f 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -2479,7 +2479,7 @@ process: - plugin: null_coalesce _use_license: - <<: *base_mods_node - query: 'mods:accessCondition[@type="use and reproduction"][@displayLabe="Creative Commons"]' + query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons"]' - plugin: callback callable: iterator_to_array - plugin: multiple_values From 41a9893c696e01c1b3ce18d239b8e2852d876350 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 12:15:39 -0300 Subject: [PATCH 09/22] Mask undesired note types. They're handled in their own dedicated fields. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index c102c83f..a856696b 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -677,7 +677,7 @@ process: - plugin: null_coalesce field_note_paragraph: - << : *base_mods_node - query: 'mods:note' + query: 'mods:note[not(@type="funding" or @type="admin")]' - plugin: callback callable: iterator_to_array - plugin: multiple_values From 598710fe815c07a60aa36824865154178ee79f71 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 12:44:54 -0300 Subject: [PATCH 10/22] Avoid null_coalescing repeatable things. --- .../migrations/dgis_nodes.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index a856696b..8ba48b08 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -635,7 +635,6 @@ process: - plugin: dgi_migrate.subproperty property: nodeValue - plugin: single_value - - plugin: null_coalesce field_item_identifier: - << : *base_mods_node query: 'mods:location/mods:holdingSimple/mods:copyInformation/mods:itemIdentifier' @@ -655,7 +654,6 @@ process: - plugin: dgi_migrate.subproperty property: nodeValue - plugin: single_value - - plugin: null_coalesce field_local_identifier: - << : *base_mods_node query: 'mods:identifier[@type="local"]' @@ -719,7 +717,6 @@ process: - plugin: dgi_migrate.subproperty property: nodeValue - plugin: single_value - - plugin: null_coalesce field_linked_agent: - << : *base_mods_node query: 'mods:name[@type="personal"]' @@ -2403,7 +2400,6 @@ process: - plugin: single_value - plugin: callback callable: array_filter - - plugin: null_coalesce field_funder: - << : *base_mods_node query: 'mods:name[@type="corporate"][mods:role/mods:roleTerm="funder"][normalize-space(mods:namePart)]' @@ -2476,7 +2472,6 @@ process: - plugin: single_value - plugin: callback callable: array_filter - - plugin: null_coalesce _use_license: - <<: *base_mods_node query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons"]' From c861e98e472cac3e0efd98af8720892e41427f61 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 14:10:12 -0300 Subject: [PATCH 11/22] Squash uses of `entity_generate`. Entities creates under it (instead of via stub migrations) would not be removed when rolling back. --- .../migrations/dgis_nodes.yml | 207 +++++++++++++----- 1 file changed, 153 insertions(+), 54 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 8ba48b08..e7b40179 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1729,22 +1729,60 @@ process: query: 'mods:typeOfResource' - plugin: callback callable: iterator_to_array + - plugin: skip_on_empty + method: process - plugin: multiple_values - - plugin: dgi_migrate.subproperty - property: nodeValue - - plugin: single_value - - plugin: callback - callable: array_filter - field_resource_type: + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: resource_types + <<: *generic_term_after + - <<: *generic_term_extract + _unspecified_resource_type: - plugin: default_value - source: '@_resource_type' default_value: Unspecified - - plugin: entity_generate - bundle: resource_types - bundle_key: vid - entity_type: taxonomy_term - value_key: name - ignore_case: *case_insensitive + - plugin: gate + use_as_key: '@_resource_type' + valid_keys: + - null + key_direction: lock + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: resource_types + _auth_value_uri: + - plugin: default_value + default_value: '' + _auth_source: + - plugin: default_value + default_value: '' + _value: + - plugin: get + source: parent_value + actual: + - plugin: get + source: + - '@_auth_source' + - '@_auth_value_uri' + - '@_value' + # XXX: Needs to be provided wherever this is used, corresponding + # to the vocab in which to do the things. + - '@_vid' + - plugin: flatten + - plugin: migration_lookup + migration: dgis_stub_terms_generic + stub_id: dgis_stub_terms_generic + - <<: *generic_term_extract + field_resource_type: + - plugin: get + source: + - '@_resource_type' + - '@_unspecified_resource_type' + - plugin: null_coalesce field_restriction_on_access: - << : *base_mods_node query: 'mods:accessCondition[@type="restriction on access"]' @@ -1753,21 +1791,6 @@ process: - plugin: multiple_values - plugin: dgi_migrate.subproperty property: nodeValue - # XXX: Was intended as outbound mapping, not inbound. Let's just comment for now. - #field_rights_statement: - # - << : *base_mods_node - # query: 'mods:accessCondition[@type="use and reproduction"]' - # - plugin: callback - # callable: iterator_to_array - # - plugin: multiple_values - # - plugin: dgi_migrate.subproperty - # property: nodeValue - # - plugin: entity_generate - # bundle: rights_statements - # bundle_key: vid - # entity_type: taxonomy_term - # value_key: name - # ignore_case: *case_insensitive field_shelf_locator: - << : *base_mods_node query: 'mods:location/mods:holdingSimple/mods:copyInformation/mods:shelfLocator' @@ -2018,22 +2041,60 @@ process: query: 'mods:extension/etd:degree/etd:level' - plugin: callback callable: iterator_to_array + - plugin: skip_on_empty + method: process - plugin: multiple_values - - plugin: dgi_migrate.subproperty - property: nodeValue - - plugin: single_value - - plugin: callback - callable: array_filter - field_degree_level: + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: degree_levels + <<: *generic_term_after + - <<: *generic_term_extract + _unspecified_degree_level: - plugin: default_value - source: '@_degree_level' default_value: Unspecified - - plugin: entity_generate - bundle: degree_levels - bundle_key: vid - entity_type: taxonomy_term - value_key: name - ignore_case: *case_insensitive + - plugin: gate + use_as_key: '@_degree_level' + valid_keys: + - null + key_direction: unlock + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: degree_levels + _auth_value_uri: + - plugin: default_value + default_value: '' + _auth_source: + - plugin: default_value + default_value: '' + _value: + - plugin: get + source: parent_value + actual: + - plugin: get + source: + - '@_auth_source' + - '@_auth_value_uri' + - '@_value' + # XXX: Needs to be provided wherever this is used, corresponding + # to the vocab in which to do the things. + - '@_vid' + - plugin: flatten + - plugin: migration_lookup + migration: dgis_stub_terms_generic + stub_id: dgis_stub_terms_generic + - <<: *generic_term_extract + field_degree_level: + - plugin: get + source: + - '@_degree_level' + - '@_unspecified_degree_level' + - plugin: null_coalesce field_department: - <<: *base_mods_node query: 'mods:extension/etd:degree/etd:discipline' @@ -2477,22 +2538,60 @@ process: query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons"]' - plugin: callback callable: iterator_to_array + - plugin: skip_on_empty + method: process - plugin: multiple_values - - plugin: dgi_migrate.subproperty - property: nodeValue - - plugin: single_value - - plugin: callback - callable: array_filter - field_use_license: + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: creative_commons_licenses_4_0 + <<: *generic_term_after + - <<: *generic_term_extract + _unspecified_use_license: - plugin: default_value - source: '@_use_license' default_value: Unspecified - - plugin: entity_generate - bundle: creative_commons_licenses_4_0 - bundle_key: vid - entity_type: taxonomy_term - value_key: name - ignore_case: *case_insensitive + - plugin: gate + use_as_key: '@_resource_type' + valid_keys: + - null + key_direction: lock + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: creative_commons_licenses_4_0 + _auth_value_uri: + - plugin: default_value + default_value: '' + _auth_source: + - plugin: default_value + default_value: '' + _value: + - plugin: get + source: parent_value + actual: + - plugin: get + source: + - '@_auth_source' + - '@_auth_value_uri' + - '@_value' + # XXX: Needs to be provided wherever this is used, corresponding + # to the vocab in which to do the things. + - '@_vid' + - plugin: flatten + - plugin: migration_lookup + migration: dgis_stub_terms_generic + stub_id: dgis_stub_terms_generic + - <<: *generic_term_extract + field_use_license: + - plugin: get + source: + - '@_use_license' + - '@_unspecified_use_license' + - plugin: flatten nid: - plugin: migration_lookup source: '@field_pid' From bd232b04d36b0943c2814d9e668f73f4412a6d7e Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 14:47:37 -0300 Subject: [PATCH 12/22] Delicious copypasta. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index e7b40179..0d9acca5 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -2553,7 +2553,7 @@ process: - plugin: default_value default_value: Unspecified - plugin: gate - use_as_key: '@_resource_type' + use_as_key: '@_use_license' valid_keys: - null key_direction: lock From b4debca54d083cfad094a4689e31226fdc9ce6ea Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 29 Jul 2024 14:52:05 -0300 Subject: [PATCH 13/22] Whatever, allow for the typo. Also, fix up the gate lock business. --- .../migrations/dgis_nodes.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 0d9acca5..e3d6e5cf 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1747,7 +1747,7 @@ process: use_as_key: '@_resource_type' valid_keys: - null - key_direction: lock + key_direction: unlock - plugin: dgi_migrate.sub_process process_values: true values: @@ -2535,7 +2535,7 @@ process: callable: array_filter _use_license: - <<: *base_mods_node - query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons"]' + query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons" or @displayLabe="Creative Commons"]' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty @@ -2556,7 +2556,7 @@ process: use_as_key: '@_use_license' valid_keys: - null - key_direction: lock + key_direction: unlock - plugin: dgi_migrate.sub_process process_values: true values: From 2303ccea6ef6a63b8126106f4737e81d72def571 Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Fri, 9 Aug 2024 10:54:15 -0300 Subject: [PATCH 14/22] Fix a transpored field name in the record_information paragraph. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index e3d6e5cf..1529ad8f 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1474,7 +1474,7 @@ process: - plugin: multiple_values - plugin: dgi_migrate.subproperty property: nodeValue - field_recording_catalog_language: + field_record_cataloging_language: - << : *nested_mods_node query: 'mods:languageOfCataloging' - plugin: callback From 38dc63b8c19008b46d61383ca8655dd4b8b48c4e Mon Sep 17 00:00:00 2001 From: Chris MacDonald <31731869+chrismacdonaldw@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:44:19 -0300 Subject: [PATCH 15/22] Refactor AssembleDate plugin to handle multiple single dates --- .../migrations/dgis_nodes.yml | 103 ++++++++++++++++-- src/Plugin/migrate/process/AssembleDate.php | 30 +++-- 2 files changed, 115 insertions(+), 18 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index 1529ad8f..daacb8be 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -55,6 +55,9 @@ destination: #translations: true validate: &validate true process: + _unspecified_term: + - plugin: default_value + default_value: 'Unspecified' _node_foxml_parsed: - plugin: dgi_migrate.load_entity source: fid @@ -236,6 +239,9 @@ process: - '@_sequence_number' - '@_constituent_sequence' - plugin: null_coalesce + # Prevent leading zeroes from crashing the migration. + - plugin: callback + callable: intval - plugin: skip_on_empty method: process _mods_xpath: @@ -1724,13 +1730,15 @@ process: default_value: genre <<: *generic_term_after - <<: *generic_term_extract - _resource_type: + _resource_type_query: - << : *base_mods_node query: 'mods:typeOfResource' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty method: process + _resource_type: + - << : *_resource_type_query - plugin: multiple_values - plugin: dgi_migrate.sub_process process_values: true @@ -1741,8 +1749,9 @@ process: <<: *generic_term_after - <<: *generic_term_extract _unspecified_resource_type: - - plugin: default_value - default_value: Unspecified + - <<: *_resource_type_query + - plugin: get + source: '@_unspecified_term' - plugin: gate use_as_key: '@_resource_type' valid_keys: @@ -1998,7 +2007,7 @@ process: validate: *validate field_use_and_reproduction: - << : *base_mods_node - query: 'mods:accessCondition[@type="use and reproduction"]' + query: 'mods:accessCondition[@type="use and reproduction" or @type="Use and Reproduction"]' - plugin: callback callable: iterator_to_array - plugin: multiple_values @@ -2036,13 +2045,15 @@ process: default_value: degree_names <<: *generic_term_after - <<: *generic_term_extract - _degree_level: + _degree_level_query: - <<: *base_mods_node query: 'mods:extension/etd:degree/etd:level' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty method: process + _degree_level: + - <<: *_degree_level_query - plugin: multiple_values - plugin: dgi_migrate.sub_process process_values: true @@ -2053,8 +2064,9 @@ process: <<: *generic_term_after - <<: *generic_term_extract _unspecified_degree_level: - - plugin: default_value - default_value: Unspecified + - <<: *_degree_level_query + - plugin: get + source: '@_unspecified_term' - plugin: gate use_as_key: '@_degree_level' valid_keys: @@ -2533,13 +2545,15 @@ process: - plugin: single_value - plugin: callback callable: array_filter - _use_license: + _use_license_query: - <<: *base_mods_node - query: 'mods:accessCondition[@type="use and reproduction"][@displayLabel="Creative Commons" or @displayLabe="Creative Commons"]' + query: 'mods:accessCondition[@type="use and reproduction" or @type="Use and Reproduction"][@displayLabel="Creative Commons" or @displayLabe="Creative Commons"]' - plugin: callback callable: iterator_to_array - plugin: skip_on_empty method: process + _use_license: + - <<: *_use_license_query - plugin: multiple_values - plugin: dgi_migrate.sub_process process_values: true @@ -2550,8 +2564,9 @@ process: <<: *generic_term_after - <<: *generic_term_extract _unspecified_use_license: - - plugin: default_value - default_value: Unspecified + - <<: *_use_license_query + - plugin: get + source: '@_unspecified_term' - plugin: gate use_as_key: '@_use_license' valid_keys: @@ -2592,6 +2607,72 @@ process: - '@_use_license' - '@_unspecified_use_license' - plugin: flatten + _rights_statement_query: + - <<: *base_mods_node + query: 'mods:accessCondition[@type="rights statement"]' + - plugin: callback + callable: iterator_to_array + - plugin: skip_on_empty + method: process + _rights_statement: + - <<: *_rights_statement_query + - plugin: multiple_values + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: rights_statements + <<: *generic_term_after + - <<: *generic_term_extract + - plugin: single_value + - plugin: callback + callable: array_filter + - plugin: null_coalesce + _unspecified_rights_statement: + - <<: *_rights_statement_query + - plugin: get + source: '@_unspecified_term' + - plugin: gate + use_as_key: '@_rights_statement' + valid_keys: + - null + key_direction: unlock + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: rights_statements + _auth_value_uri: + - plugin: default_value + default_value: '' + _auth_source: + - plugin: default_value + default_value: '' + _value: + - plugin: get + source: parent_value + actual: + - plugin: get + source: + - '@_auth_source' + - '@_auth_value_uri' + - '@_value' + # XXX: Needs to be provided wherever this is used, corresponding + # to the vocab in which to do the things. + - '@_vid' + - plugin: flatten + - plugin: migration_lookup + migration: dgis_stub_terms_generic + stub_id: dgis_stub_terms_generic + - <<: *generic_term_extract + field_rights_statement: + - plugin: get + source: + - '@_rights_statement' + - '@_unspecified_rights_statement' + - plugin: null_coalesce nid: - plugin: migration_lookup source: '@field_pid' diff --git a/src/Plugin/migrate/process/AssembleDate.php b/src/Plugin/migrate/process/AssembleDate.php index 86a6078a..17126f0d 100644 --- a/src/Plugin/migrate/process/AssembleDate.php +++ b/src/Plugin/migrate/process/AssembleDate.php @@ -18,7 +18,7 @@ * The output is handled thus: * - If a range_start, or a range_end, or both, are provided and not empty, an * EDTF-style date range will be assembled, and any results from single_date - * will be ignored. + * will be combined. * - If neither a range_start nor a range_end are provided or are empty, but the * single_date is provided and has a value, it is returned. * - If no provided property has a value, null will be returned. @@ -37,7 +37,8 @@ * @code * process: * - plugin: dgi_migrate.process.assemble_date - * single_date: 2001-01-01 + * single_date: + * - 2001-01-01 * range_start: 2002-02-02 * range_end: 2003-03-03 * indicate_open: false @@ -96,7 +97,7 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition 'range_start' => $this->configuration['range_start'] ?? NULL, 'range_end' => $this->configuration['range_end'] ?? NULL, ]; - if (!array_filter($this->dates)) { + if (empty($this->dates['single_date']) && !$this->dates['range_start'] && !$this->dates['range_end']) { throw new MigrateException('Plugin dgi_migrate.process.assemble_date requires at least one of the three properties, "single_date", "range_start", or "range_end" to be provided.'); } $indicate_open = $this->configuration['indicate_open'] ?? FALSE; @@ -108,11 +109,26 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { - $return_value = $this->getDateRange($value, $migrate_executable, $row); - if (!$return_value) { - $return_value = $this->getValues ? $row->get($this->dates['single_date']) : $this->dates['single_date']; + $return_dates = []; + + $date_range = $this->getDateRange($value, $migrate_executable, $row); + if ($date_range !== NULL) { + $return_dates[] = $date_range; + } + + // Get single dates and add them to return_dates + $single_dates = $this->getValues ? $row->get($this->dates['single_date']) : $this->dates['single_date']; + if (is_array($single_dates)) { + $return_dates = array_merge($return_dates, $single_dates); + } elseif ($single_dates !== NULL) { + $return_dates[] = $single_dates; } - return $return_value; + + if (count($return_dates) === 1) { + return $return_dates[0]; + } + + return $return_dates; } /** From c7b9a52f7b2c77f0cf6b49ddf92e3364d7f002cd Mon Sep 17 00:00:00 2001 From: Chris MacDonald <31731869+chrismacdonaldw@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:43:25 -0300 Subject: [PATCH 16/22] Refactor queries to not use anchors --- .../migrations/dgis_nodes.yml | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index daacb8be..ed09902f 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1735,10 +1735,11 @@ process: query: 'mods:typeOfResource' - plugin: callback callable: iterator_to_array + _resource_type: + - plugin: get + source: '@_resource_type_query' - plugin: skip_on_empty method: process - _resource_type: - - << : *_resource_type_query - plugin: multiple_values - plugin: dgi_migrate.sub_process process_values: true @@ -1749,7 +1750,10 @@ process: <<: *generic_term_after - <<: *generic_term_extract _unspecified_resource_type: - - <<: *_resource_type_query + - plugin: get + source: '@_resource_type_query' + - plugin: skip_on_empty + method: process - plugin: get source: '@_unspecified_term' - plugin: gate @@ -2050,10 +2054,11 @@ process: query: 'mods:extension/etd:degree/etd:level' - plugin: callback callable: iterator_to_array + _degree_level: + - plugin: get + source: '@_degree_level_query' - plugin: skip_on_empty method: process - _degree_level: - - <<: *_degree_level_query - plugin: multiple_values - plugin: dgi_migrate.sub_process process_values: true @@ -2064,7 +2069,10 @@ process: <<: *generic_term_after - <<: *generic_term_extract _unspecified_degree_level: - - <<: *_degree_level_query + - plugin: get + source: '@_degree_level_query' + - plugin: skip_on_empty + method: process - plugin: get source: '@_unspecified_term' - plugin: gate @@ -2550,10 +2558,11 @@ process: query: 'mods:accessCondition[@type="use and reproduction" or @type="Use and Reproduction"][@displayLabel="Creative Commons" or @displayLabe="Creative Commons"]' - plugin: callback callable: iterator_to_array + _use_license: + - plugin: get + source: '@_use_license_query' - plugin: skip_on_empty method: process - _use_license: - - <<: *_use_license_query - plugin: multiple_values - plugin: dgi_migrate.sub_process process_values: true @@ -2564,7 +2573,10 @@ process: <<: *generic_term_after - <<: *generic_term_extract _unspecified_use_license: - - <<: *_use_license_query + - plugin: get + source: '@_use_license_query' + - plugin: skip_on_empty + method: process - plugin: get source: '@_unspecified_term' - plugin: gate @@ -2612,10 +2624,11 @@ process: query: 'mods:accessCondition[@type="rights statement"]' - plugin: callback callable: iterator_to_array + _rights_statement: + - plugin: get + source: '@_rights_statement_query' - plugin: skip_on_empty method: process - _rights_statement: - - <<: *_rights_statement_query - plugin: multiple_values - plugin: dgi_migrate.sub_process process_values: true @@ -2630,7 +2643,10 @@ process: callable: array_filter - plugin: null_coalesce _unspecified_rights_statement: - - <<: *_rights_statement_query + - plugin: get + source: '@_rights_statement_query' + - plugin: skip_on_empty + method: process - plugin: get source: '@_unspecified_term' - plugin: gate From 666581e4b397285327e0c5b2d6211cdb23a134d7 Mon Sep 17 00:00:00 2001 From: Chris MacDonald <31731869+chrismacdonaldw@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:58:12 -0300 Subject: [PATCH 17/22] Adjust for sniffer errors --- src/Plugin/migrate/process/AssembleDate.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Plugin/migrate/process/AssembleDate.php b/src/Plugin/migrate/process/AssembleDate.php index 17126f0d..8b7becb4 100644 --- a/src/Plugin/migrate/process/AssembleDate.php +++ b/src/Plugin/migrate/process/AssembleDate.php @@ -116,11 +116,12 @@ public function transform($value, MigrateExecutableInterface $migrate_executable $return_dates[] = $date_range; } - // Get single dates and add them to return_dates + // Get single dates and add them to return_dates. $single_dates = $this->getValues ? $row->get($this->dates['single_date']) : $this->dates['single_date']; if (is_array($single_dates)) { $return_dates = array_merge($return_dates, $single_dates); - } elseif ($single_dates !== NULL) { + } + elseif ($single_dates !== NULL) { $return_dates[] = $single_dates; } From 95771391c383388fb0baa54db5f25a7517b17c34 Mon Sep 17 00:00:00 2001 From: Chris MacDonald <31731869+chrismacdonaldw@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:54:06 -0300 Subject: [PATCH 18/22] Update according to Adam's feedback. --- src/Plugin/migrate/process/AssembleDate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Plugin/migrate/process/AssembleDate.php b/src/Plugin/migrate/process/AssembleDate.php index 8b7becb4..ee806002 100644 --- a/src/Plugin/migrate/process/AssembleDate.php +++ b/src/Plugin/migrate/process/AssembleDate.php @@ -97,7 +97,7 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition 'range_start' => $this->configuration['range_start'] ?? NULL, 'range_end' => $this->configuration['range_end'] ?? NULL, ]; - if (empty($this->dates['single_date']) && !$this->dates['range_start'] && !$this->dates['range_end']) { + if (!array_filter($this->dates)) { throw new MigrateException('Plugin dgi_migrate.process.assemble_date requires at least one of the three properties, "single_date", "range_start", or "range_end" to be provided.'); } $indicate_open = $this->configuration['indicate_open'] ?? FALSE; @@ -126,7 +126,7 @@ public function transform($value, MigrateExecutableInterface $migrate_executable } if (count($return_dates) === 1) { - return $return_dates[0]; + return reset($return_dates); } return $return_dates; From 4f14aa8ce54a8c850e6496b49882e7747603530d Mon Sep 17 00:00:00 2001 From: Chris MacDonald <31731869+chrismacdonaldw@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:09:47 -0300 Subject: [PATCH 19/22] Update cataloging language to reflect changes to content type. --- .../migrations/dgis_nodes.yml | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index ed09902f..cdfd6b09 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -1472,6 +1472,10 @@ process: type: record_information process_values: true values: + _mods_xpath: + # XXX: Copy here so it's available for further subprocessing. + - plugin: get + source: parent_row/dest/_mods_xpath field_description_standard: - << : *nested_mods_node query: 'mods:descriptionStandard' @@ -1481,13 +1485,21 @@ process: - plugin: dgi_migrate.subproperty property: nodeValue field_record_cataloging_language: - - << : *nested_mods_node - query: 'mods:languageOfCataloging' + - <<: *nested_mods_node + query: 'mods:languageOfCataloging[normalize-space()]' - plugin: callback callable: iterator_to_array + - plugin: skip_on_empty + method: process - plugin: multiple_values - - plugin: dgi_migrate.subproperty - property: nodeValue + - plugin: dgi_migrate.sub_process + process_values: true + values: + _vid: + - plugin: default_value + default_value: language + <<: *generic_term_after + - <<: *generic_term_extract _field_record_change_date_single: - << : *nested_mods_node query: 'mods:recordChangeDate[not(@point)]' From 7924a30af0ac5203e8e100bf0f8607f1e450361c Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Mon, 16 Sep 2024 14:36:03 -0300 Subject: [PATCH 20/22] Define the namespace if we are going to query for it. --- .../dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml index ed09902f..9ab08ce7 100644 --- a/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml +++ b/modules/dgi_migrate_foxml_standard_mods/migrations/dgis_nodes.yml @@ -260,6 +260,7 @@ process: - plugin: dgi_migrate.process.xml.xpath namespaces: mods: 'http://www.loc.gov/mods/v3' + etd: 'http://www.ndltd.org/standards/metadata/etdms/1.0' xsi: 'http://www.w3.org/2001/XMLSchema-instance' xlink: 'http://www.w3.org/1999/xlink' _mods_node: From 7a127d29781d4d1ec22cae8afc9b9f33b101fc63 Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Mon, 16 Sep 2024 14:44:21 -0300 Subject: [PATCH 21/22] Add to alter too. --- .../modules/xslt/migration_alterations/dgis_nodes.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/dgi_migrate_foxml_standard_mods/modules/xslt/migration_alterations/dgis_nodes.inc b/modules/dgi_migrate_foxml_standard_mods/modules/xslt/migration_alterations/dgis_nodes.inc index 1fd34d1b..d89456f0 100644 --- a/modules/dgi_migrate_foxml_standard_mods/modules/xslt/migration_alterations/dgis_nodes.inc +++ b/modules/dgi_migrate_foxml_standard_mods/modules/xslt/migration_alterations/dgis_nodes.inc @@ -40,6 +40,7 @@ function _dgi_migrate_foxml_standard_mods_xslt_dgis_nodes_migration_alterations( - plugin: dgi_migrate.process.xml.xpath namespaces: mods: 'http://www.loc.gov/mods/v3' + etd: 'http://www.ndltd.org/standards/metadata/etdms/1.0' xsi: 'http://www.w3.org/2001/XMLSchema-instance' xlink: 'http://www.w3.org/1999/xlink' EOI From e98b6835183db25aa15fdc5acf3bfbd4d5a9a952 Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Fri, 20 Sep 2024 11:33:40 -0300 Subject: [PATCH 22/22] 'Murica behavioring. https://github.com/discoverygarden/dgi_migrate/blob/main/src/Plugin/migrate/process/MissingBehaviorTrait.php#L62 --- src/Plugin/migrate/process/Subindex.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin/migrate/process/Subindex.php b/src/Plugin/migrate/process/Subindex.php index aa9de0cb..6cc06944 100644 --- a/src/Plugin/migrate/process/Subindex.php +++ b/src/Plugin/migrate/process/Subindex.php @@ -25,7 +25,7 @@ * dereference, to attempt to use as the index to access. * - "skip_row_if_missing": Deprecated in favour of "missing_behavior". A flag * to indicate if the row should be skipped when we find there's no value. - * - "missing_behaviour": A string indicating what should happen when we fail + * - "missing_behavior": A string indicating what should happen when we fail * to find the target value. One of: * - "abort": Stop the migration, throwing an exception. * - "skip_process": Stop processing the property.