app/parsers/bulkrax/application_parser.rb in bulkrax-1.0.2 vs app/parsers/bulkrax/application_parser.rb in bulkrax-2.0.0

- old
+ new

@@ -1,17 +1,17 @@ # frozen_string_literal: true module Bulkrax - class ApplicationParser - attr_accessor :importerexporter + class ApplicationParser # rubocop:disable Metrics/ClassLength + attr_accessor :importerexporter, :headers alias importer importerexporter alias exporter importerexporter - delegate :only_updates, :limit, :current_run, :errors, - :seen, :increment_counters, :parser_fields, :user, - :exporter_export_path, :exporter_export_zip_path, :importer_unzip_path, :validate_only, - :status, :status_info, :status_at, - to: :importerexporter + delegate :only_updates, :limit, :current_run, :errors, :mapping, + :seen, :increment_counters, :parser_fields, :user, :keys_without_numbers, + :key_without_numbers, :status, :status_info, :status_at, + :exporter_export_path, :exporter_export_zip_path, :importer_unzip_path, :validate_only, + to: :importerexporter def self.parser_fields {} end @@ -23,10 +23,11 @@ true end def initialize(importerexporter) @importerexporter = importerexporter + @headers = [] end # @api def entry_class raise StandardError, 'must be defined' @@ -41,26 +42,60 @@ def records(_opts = {}) raise StandardError, 'must be defined' end def source_identifier - @source_identifier ||= identifier_hash.values.first&.[]("from")&.first&.to_sym || :source_identifier + @source_identifier ||= get_field_mapping_hash_for('source_identifier')&.values&.first&.[]('from')&.first&.to_sym || :source_identifier end def work_identifier - @work_identifier ||= identifier_hash.keys.first&.to_sym || :source + @work_identifier ||= get_field_mapping_hash_for('source_identifier')&.keys&.first&.to_sym || :source end - def identifier_hash - @identifier_hash ||= importerexporter.mapping.select do |_, h| - h.key?("source_identifier") - end - raise StandardError, "more than one source_identifier declared: #{@identifier_hash.keys.join(', ')}" if @identifier_hash.length > 1 + def related_parents_raw_mapping + @related_parents_raw_mapping ||= get_field_mapping_hash_for('related_parents_field_mapping')&.values&.first&.[]('from')&.first + end - @identifier_hash + def related_parents_parsed_mapping + @related_parents_parsed_mapping ||= get_field_mapping_hash_for('related_parents_field_mapping')&.keys&.first end + def related_children_raw_mapping + @related_children_raw_mapping ||= get_field_mapping_hash_for('related_children_field_mapping')&.values&.first&.[]('from')&.first + end + + def related_children_parsed_mapping + @related_children_parsed_mapping ||= get_field_mapping_hash_for('related_children_field_mapping')&.keys&.first + end + + def get_field_mapping_hash_for(key) + return instance_variable_get("@#{key}_hash") if instance_variable_get("@#{key}_hash").present? + + instance_variable_set( + "@#{key}_hash", + importerexporter.mapping.with_indifferent_access.select { |_, h| h.key?(key) } + ) + raise StandardError, "more than one #{key} declared: #{instance_variable_get("@#{key}_hash").keys.join(', ')}" if instance_variable_get("@#{key}_hash").length > 1 + + instance_variable_get("@#{key}_hash") + end + + def collection_field_mapping + ActiveSupport::Deprecation.warn( + 'Creating Collections using the collection_field_mapping will no longer be supported as of Bulkrax version 3.0.' \ + ' Please configure Bulkrax to use related_parents_field_mapping and related_children_field_mapping instead.' + ) + Bulkrax.collection_field_mapping[self.entry_class.to_s]&.to_sym || :collection + end + + def model_field_mappings + model_mappings = Bulkrax.field_mappings[self.class.to_s]&.dig('model', :from) || [] + model_mappings |= ['model'] + + model_mappings + end + def perform_method if self.validate_only 'perform_now' else 'perform_later' @@ -89,80 +124,23 @@ path ) path end + # Base path for imported and exported files + def base_path(type = 'import') + ENV['HYKU_MULTITENANT'] ? File.join(Bulkrax.send("#{type}_path"), Site.instance.account.name) : Bulkrax.send("#{type}_path") + end + # Path where we'll store the import metadata and files # this is used for uploaded and cloud files def path_for_import - @path_for_import = File.join(Bulkrax.import_path, importerexporter.path_string) + @path_for_import = File.join(base_path, importerexporter.path_string) FileUtils.mkdir_p(@path_for_import) unless File.exist?(@path_for_import) @path_for_import end - # Optional, only used by certain parsers - # Other parsers should override with a custom or empty method - # Will be skipped unless the #record is a Hash - def create_parent_child_relationships - parents.each do |key, value| - parent = entry_class.where( - identifier: key, - importerexporter_id: importerexporter.id, - importerexporter_type: 'Bulkrax::Importer' - ).first - - # not finding the entries here indicates that the given identifiers are incorrect - # in that case we should log that - children = value.map do |child| - entry_class.where( - identifier: child, - importerexporter_id: importerexporter.id, - importerexporter_type: 'Bulkrax::Importer' - ).first - end.compact.uniq - - if parent.present? && (children.length != value.length) - # Increment the failures for the number we couldn't find - # Because all of our entries have been created by now, if we can't find them, the data is wrong - Rails.logger.error("Expected #{value.length} children for parent entry #{parent.id}, found #{children.length}") - break if children.empty? - Rails.logger.warn("Adding #{children.length} children to parent entry #{parent.id} (expected #{value.length})") - end - parent_id = parent.id - child_entry_ids = children.map(&:id) - ChildRelationshipsJob.perform_later(parent_id, child_entry_ids, current_run.id) - end - rescue StandardError => e - status_info(e) - end - - def parents - @parents ||= setup_parents - end - - def setup_parents - pts = [] - records.each do |record| - r = if record.respond_to?(:to_h) - record.to_h - else - record - end - next unless r.is_a?(Hash) - children = if r[:children].is_a?(String) - r[:children].split(/\s*[:;|]\s*/) - else - r[:children] - end - next if children.blank? - pts << { - r[source_identifier] => children - } - end - pts.blank? ? pts : pts.inject(:merge) - end - def setup_export_file raise StandardError, 'must be defined' if exporter? end def write_files @@ -286,14 +264,11 @@ end private def real_import_file_path - if file? && zip? - unzip(parser_fields['import_file_path']) - return importer_unzip_path - else - parser_fields['import_file_path'] - end + return importer_unzip_path if file? && zip? + + parser_fields['import_file_path'] end end end