app/models/spotlight/resources/iiif_manifest.rb in blacklight-spotlight-2.9.0 vs app/models/spotlight/resources/iiif_manifest.rb in blacklight-spotlight-2.10.0

- old
+ new

@@ -68,11 +68,11 @@ def add_label return unless title_fields.present? && manifest.try(:label) Array.wrap(title_fields).each do |field| - solr_hash[field] = json_ld_value(manifest.label) + solr_hash[field] = metadata_class.new(manifest).label end end def add_image_urls solr_hash[tile_source_field] = image_urls @@ -94,17 +94,10 @@ hash[field.field] = value end end - def json_ld_value(value) - return value['@value'] if value.is_a?(Hash) - return value.find { |v| v['@language'] == default_json_ld_language }.try(:[], '@value') if value.is_a?(Array) - - value - end - def create_sidecars_for(*keys) missing_keys(keys).each do |k| exhibit.custom_fields.create! label: k, readonly_field: true end @exhibit_custom_fields = nil @@ -162,14 +155,10 @@ def title_fields Spotlight::Engine.config.iiif_title_fields || blacklight_config.index.try(:title_field) end - def default_json_ld_language - Spotlight::Engine.config.default_json_ld_language - end - def sidecar @sidecar ||= document_model.new(id: compound_id).sidecar(exhibit) end def document_model @@ -193,10 +182,16 @@ def to_solr metadata_hash.merge(manifest_level_metadata) end + def label + return unless manifest.try(:label) + + Array(json_ld_value(manifest.label)).map { |v| html_sanitize(v) }.first + end + private attr_reader :manifest def metadata @@ -208,26 +203,96 @@ return {} unless metadata.is_a?(Array) metadata.each_with_object({}) do |md, hash| next unless md['label'] && md['value'] - hash[md['label']] ||= [] - hash[md['label']] += Array(md['value']) + label = Array(json_ld_value(md['label'])).first + + hash[label] ||= [] + hash[label] += Array(json_ld_value(md['value'])).map { |v| html_sanitize(v) } end end def manifest_level_metadata manifest_fields.each_with_object({}) do |field, hash| next unless manifest.respond_to?(field) && manifest.send(field).present? hash[field.capitalize] ||= [] - hash[field.capitalize] += Array(manifest.send(field)) + hash[field.capitalize] += Array(json_ld_value(manifest.send(field))).map { |v| html_sanitize(v) } end end def manifest_fields %w(attribution description license) + end + + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity + def json_ld_value(value) + case value + # In the case where multiple values are supplied, clients must use the following algorithm to determine which values to display to the user. + when Array + # IIIF v2, multivalued monolingual, or multivalued multilingual values + + # If none of the values have a language associated with them, the client must display all of the values. + if value.none? { |v| v.is_a?(Hash) && v.key?('@language') } + value.map { |v| json_ld_value(v) } + # If any of the values have a language associated with them, the client must display all of the values associated with the language that best + # matches the language preference. + elsif value.any? { |v| v.is_a?(Hash) && v['@language'] == default_json_ld_language } + value.select { |v| v.is_a?(Hash) && v['@language'] == default_json_ld_language }.map { |v| v['@value'] } + # If all of the values have a language associated with them, and none match the language preference, the client must select a language + # and display all of the values associated with that language. + elsif value.all? { |v| v.is_a?(Hash) && v.key?('@language') } + selected_json_ld_language = value.find { |v| v.is_a?(Hash) && v.key?('@language') } + + value.select { |v| v.is_a?(Hash) && v['@language'] == selected_json_ld_language['@language'] } + .map { |v| v['@value'] } + # If some of the values have a language associated with them, but none match the language preference, the client must display all of the values + # that do not have a language associated with them. + else + value.select { |v| !v.is_a?(Hash) || !v.key?('@language') }.map { |v| json_ld_value(v) } + end + when Hash + # IIIF v2 single-valued value + if value.key? '@value' + value['@value'] + # IIIF v3 multilingual(?), multivalued(?) values + # If all of the values are associated with the none key, the client must display all of those values. + elsif value.keys == ['none'] + value['none'] + # If any of the values have a language associated with them, the client must display all of the values associated with the language + # that best matches the language preference. + elsif value.key? default_json_ld_language + value[default_json_ld_language] + # If some of the values have a language associated with them, but none match the language preference, the client must display all + # of the values that do not have a language associated with them. + elsif value.key? 'none' + value['none'] + # If all of the values have a language associated with them, and none match the language preference, the client must select a + # language and display all of the values associated with that language. + else + value.values.first + end + else + # plain old string/number/boolean + value + end + end + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity + + def html_sanitize(value) + return value unless value.is_a? String + + html_sanitizer.sanitize(value) + end + + def html_sanitizer + @html_sanitizer ||= Rails::Html::FullSanitizer.new + end + + def default_json_ld_language + Spotlight::Engine.config.default_json_ld_language end end end end end