hyrax 3.4.1 → 3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +26 -17
  3. data/.dassie/.env +1 -1
  4. data/.dassie/Gemfile +1 -1
  5. data/.dassie/app/forms/collection_resource_form.rb +8 -0
  6. data/.dassie/app/indexers/collection_resource_indexer.rb +8 -0
  7. data/.dassie/app/models/collection_resource.rb +35 -0
  8. data/.dassie/config/initializers/file_services.rb +4 -0
  9. data/.dassie/config/initializers/hyrax.rb +2 -1
  10. data/.dassie/config/metadata/collection_resource.yaml +23 -0
  11. data/.dassie/db/seeds.rb +2 -0
  12. data/.dassie/spec/forms/collection_resource_form_spec.rb +13 -0
  13. data/.dassie/spec/indexers/collection_resource_indexer_spec.rb +14 -0
  14. data/.dassie/spec/models/collection_resource_spec.rb +13 -0
  15. data/.regen +1 -1
  16. data/.rubocop.yml +1 -1
  17. data/.rubocop_fixme.yml +19 -2
  18. data/CONTAINERS.md +18 -13
  19. data/Dockerfile +2 -2
  20. data/app/assets/javascripts/hyrax/collections_v2.es6 +13 -0
  21. data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +1 -3
  22. data/app/controllers/hyrax/dashboard/collections_controller.rb +159 -75
  23. data/app/controllers/hyrax/single_use_links_viewer_controller.rb +1 -1
  24. data/app/forms/hyrax/forms/collection_form.rb +1 -1
  25. data/app/forms/hyrax/forms/pcdm_collection_form.rb +29 -2
  26. data/app/forms/hyrax/forms/resource_form.rb +15 -1
  27. data/app/forms/hyrax/forms/widgets/admin_set_visibility.rb +1 -1
  28. data/app/indexers/hyrax/pcdm_collection_indexer.rb +0 -1
  29. data/app/jobs/characterize_job.rb +5 -1
  30. data/app/jobs/import_url_job.rb +4 -6
  31. data/app/jobs/valkyrie_ingest_job.rb +15 -77
  32. data/app/models/admin_set.rb +8 -0
  33. data/app/models/concerns/hyrax/collection_behavior.rb +1 -1
  34. data/app/models/concerns/hyrax/user.rb +11 -0
  35. data/app/models/concerns/hyrax/work_behavior.rb +1 -1
  36. data/app/models/featured_work_list.rb +0 -1
  37. data/app/models/hyrax/file_metadata.rb +32 -2
  38. data/app/models/hyrax/file_set.rb +1 -3
  39. data/app/models/hyrax/group.rb +19 -0
  40. data/app/models/hyrax/pcdm_collection.rb +0 -1
  41. data/app/models/job_io_wrapper.rb +1 -1
  42. data/app/presenters/hyrax/member_presenter_factory.rb +2 -4
  43. data/app/presenters/hyrax/work_show_presenter.rb +3 -3
  44. data/app/services/hyrax/access_control_list.rb +7 -6
  45. data/app/services/hyrax/adapters/nesting_index_adapter.rb +3 -3
  46. data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +3 -5
  47. data/app/services/hyrax/collections/collection_member_service.rb +3 -5
  48. data/app/services/hyrax/listeners/file_metadata_listener.rb +11 -0
  49. data/app/services/hyrax/listeners/member_cleanup_listener.rb +14 -18
  50. data/app/services/hyrax/multiple_membership_checker.rb +2 -0
  51. data/app/services/hyrax/valkyrie_persist_derivatives.rb +50 -0
  52. data/app/services/hyrax/valkyrie_upload.rb +94 -0
  53. data/app/services/hyrax/workflow/workflow_importer.rb +7 -9
  54. data/app/services/hyrax/workflow/workflow_schema.rb +3 -5
  55. data/app/strategies/hyrax/strategies/yaml_strategy.rb +4 -6
  56. data/app/uploaders/hyrax/uploaded_file_uploader.rb +4 -4
  57. data/app/validators/hyrax/collection_membership_validator.rb +16 -15
  58. data/app/views/catalog/_index_header_list_default.html.erb +8 -1
  59. data/app/views/catalog/_thumbnail_list_default.html.erb +8 -3
  60. data/app/views/collections/edit_fields/_based_near.html.erb +7 -7
  61. data/app/views/hyrax/dashboard/collections/_form.html.erb +3 -2
  62. data/app/views/hyrax/dashboard/collections/_form_branding.html.erb +1 -0
  63. data/app/views/hyrax/dashboard/sidebar/_activity.html.erb +1 -1
  64. data/app/views/hyrax/my/works/_tabs.html.erb +6 -1
  65. data/chart/hyrax/Chart.yaml +10 -6
  66. data/chart/hyrax/templates/_helpers.tpl +4 -0
  67. data/chart/hyrax/templates/cron-embargo.yaml +5 -0
  68. data/chart/hyrax/templates/cron-lease.yaml +5 -0
  69. data/chart/hyrax/templates/deployment-worker.yaml +11 -0
  70. data/chart/hyrax/templates/ingress.yaml +7 -6
  71. data/chart/hyrax/values.yaml +152 -0
  72. data/config/features.rb +48 -50
  73. data/config/initializers/{valkryrie_storage.rb → storage_adapter_initializer.rb} +5 -0
  74. data/config/locales/hyrax.de.yml +12 -12
  75. data/docker-compose.yml +1 -0
  76. data/documentation/developing-your-hyrax-based-app.md +1 -1
  77. data/documentation/legacyREADME.md +1 -1
  78. data/hyrax.gemspec +5 -3
  79. data/lib/generators/hyrax/collection_resource/USAGE +20 -0
  80. data/lib/generators/hyrax/collection_resource/collection_resource_generator.rb +133 -0
  81. data/lib/generators/hyrax/collection_resource/templates/collection.rb.erb +34 -0
  82. data/lib/generators/hyrax/collection_resource/templates/collection_form.rb.erb +7 -0
  83. data/lib/generators/hyrax/collection_resource/templates/collection_form_spec.rb.erb +13 -0
  84. data/lib/generators/hyrax/collection_resource/templates/collection_indexer.rb.erb +7 -0
  85. data/lib/generators/hyrax/collection_resource/templates/collection_indexer_spec.rb.erb +13 -0
  86. data/lib/generators/hyrax/collection_resource/templates/collection_metadata.yaml +22 -0
  87. data/lib/generators/hyrax/collection_resource/templates/collection_spec.rb.erb +12 -0
  88. data/lib/generators/hyrax/install_generator.rb +9 -0
  89. data/lib/hyrax/configuration.rb +12 -0
  90. data/lib/hyrax/publisher.rb +4 -0
  91. data/lib/hyrax/specs/shared_specs/hydra_works.rb +0 -1
  92. data/lib/hyrax/transactions/collection_update.rb +2 -0
  93. data/lib/hyrax/transactions/container.rb +10 -0
  94. data/lib/hyrax/transactions/steps/save_collection_banner.rb +59 -0
  95. data/lib/hyrax/transactions/steps/save_collection_logo.rb +109 -0
  96. data/lib/hyrax/version.rb +1 -1
  97. data/lib/wings/active_fedora_converter/file_metadata_node.rb +48 -0
  98. data/lib/wings/active_fedora_converter/instance_builder.rb +68 -0
  99. data/lib/wings/active_fedora_converter.rb +3 -3
  100. data/lib/wings/services/custom_queries/find_file_metadata.rb +19 -8
  101. data/lib/wings/valkyrie/query_service.rb +4 -6
  102. data/template.rb +1 -1
  103. metadata +63 -13
  104. data/app/views/catalog/_index_header_list_hyrax_pcdm_collection.html.erb +0 -4
@@ -1,6 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hyrax
4
+ ##
5
+ # Casts a resource to an associated FileMetadata
6
+ #
7
+ # @param [Valkyrie::StorageAdapter::File] file
8
+ #
9
+ # @return [Hyrax::FileMetadata]
10
+ # @raise [ArgumentError]
11
+ def self.FileMetadata(file)
12
+ raise(ArgumentError, "Expected a Valkyrie::StorageAdapter::File; got #{file.class}: #{file}") if
13
+ file.is_a?(Valkyrie::Resource)
14
+
15
+ Hyrax.custom_queries.find_file_metadata_by(id: file.id)
16
+ rescue Hyrax::ObjectNotFoundError, Ldp::BadRequest
17
+ Hyrax.logger.debug('Could not find an existing metadata node for file ' \
18
+ "with id #{file.id}. Initializing a new one")
19
+
20
+ FileMetadata.new(file_identifier: file.id, alternative_ids: [file.id])
21
+ end
22
+
4
23
  class FileMetadata < Valkyrie::Resource
5
24
  # Include mime-types for Hydra Derivatives mime-type checking. We may want
6
25
  # to move this logic someday.
@@ -39,7 +58,7 @@ module Hyrax
39
58
  end
40
59
 
41
60
  attribute :file_identifier, Valkyrie::Types::ID # id of the file stored by the storage adapter
42
- attribute :alternate_ids, Valkyrie::Types::Set.of(Valkyrie::Types::ID) # id of the Hydra::PCDM::File which holds metadata and the file in ActiveFedora
61
+ attribute :alternate_ids, Valkyrie::Types::Set.of(Valkyrie::Types::ID) # id of the file, populated for queryability
43
62
  attribute :file_set_id, ::Valkyrie::Types::ID # id of parent file set resource
44
63
 
45
64
  # all remaining attributes are on AF::File metadata_node unless otherwise noted
@@ -107,7 +126,9 @@ module Hyrax
107
126
  attribute :aspect_ratio, ::Valkyrie::Types::Set
108
127
 
109
128
  # @param [ActionDispatch::Http::UploadedFile] file
129
+ # @deprecated Use #new instead; for removal in 4.0.0
110
130
  def self.for(file:)
131
+ Deprecation.warn "#{self.class}##{__method__} is deprecated; use #new instead."
111
132
  new(label: file.original_filename,
112
133
  original_filename: file.original_filename,
113
134
  mime_type: file.content_type)
@@ -155,8 +176,17 @@ module Hyrax
155
176
  ''
156
177
  end
157
178
 
179
+ ##
180
+ # @return [Valkyrie::StorageAdapter::File]
181
+ #
182
+ # @raise [Valkyrie::StorageAdapter::AdapterNotFoundError] if no adapter
183
+ # could be found matching the file_identifier's scheme
184
+ # @raise [Valkyrie::StorageAdapter::FileNotFound] when the file can't
185
+ # be found in the registered adapter
158
186
  def file
159
- Hyrax.storage_adapter.find_by(id: file_identifier)
187
+ Valkyrie::StorageAdapter
188
+ .adapter_for(id: file_identifier)
189
+ .find_by(id: file_identifier)
160
190
  end
161
191
  end
162
192
  end
@@ -34,9 +34,7 @@ module Hyrax
34
34
  include Hyrax::Schema(:basic_metadata)
35
35
 
36
36
  def self.model_name(name_class: Hyrax::Name)
37
- @_model_name ||= begin
38
- name_class.new(self, nil, 'FileSet')
39
- end
37
+ @_model_name ||= name_class.new(self, nil, 'FileSet')
40
38
  end
41
39
 
42
40
  class_attribute :characterization_proxy
@@ -7,12 +7,31 @@ module Hyrax
7
7
  DEFAULT_NAME_PREFIX
8
8
  end
9
9
 
10
+ ##
11
+ # @return [Hyrax::Group]
12
+ def self.from_agent_key(key)
13
+ new(key.delete_prefix(name_prefix))
14
+ end
15
+
10
16
  def initialize(name)
11
17
  @name = name
12
18
  end
13
19
 
14
20
  attr_reader :name
15
21
 
22
+ ##
23
+ # @return [Boolean]
24
+ def ==(other)
25
+ other.class == self.class && other.name == name
26
+ end
27
+
28
+ ##
29
+ # @return [String] a local identifier for this group; for use (e.g.) in ACL
30
+ # data
31
+ def agent_key
32
+ self.class.name_prefix + name
33
+ end
34
+
16
35
  def to_sipity_agent
17
36
  sipity_agent || create_sipity_agent!
18
37
  end
@@ -41,7 +41,6 @@ module Hyrax
41
41
  #
42
42
  class PcdmCollection < Hyrax::Resource
43
43
  include Hyrax::Schema(:core_metadata)
44
- include Hyrax::Schema(:basic_metadata)
45
44
 
46
45
  attribute :collection_type_gid, Valkyrie::Types::String
47
46
  attribute :member_ids, Valkyrie::Types::Array.of(Valkyrie::Types::ID).meta(ordered: true)
@@ -94,7 +94,7 @@ class JobIoWrapper < ApplicationRecord
94
94
 
95
95
  def extracted_original_name
96
96
  eon = uploaded_file.uploader.filename if uploaded_file
97
- eon ||= File.basename(path) if path.present? # note: uploader.filename is `nil` with uncached remote files (e.g. AWSFile)
97
+ eon ||= File.basename(path) if path.present? # NOTE: uploader.filename is `nil` with uncached remote files (e.g. AWSFile)
98
98
  eon
99
99
  end
100
100
 
@@ -47,13 +47,11 @@ module Hyrax
47
47
  # in order.
48
48
  # Arbitrarily maxed at 10 thousand; had to specify rows due to solr's default of 10
49
49
  def file_set_ids
50
- @file_set_ids ||= begin
51
- Hyrax::SolrService.query("{!field f=has_model_ssim}FileSet",
50
+ @file_set_ids ||= Hyrax::SolrService.query("{!field f=has_model_ssim}FileSet",
52
51
  rows: 10_000,
53
52
  fl: Hyrax.config.id_field,
54
53
  fq: "{!join from=ordered_targets_ssim to=id}id:\"#{id}/list_source\"")
55
- .flat_map { |x| x.fetch(Hyrax.config.id_field, []) }
56
- end
54
+ .flat_map { |x| x.fetch(Hyrax.config.id_field, []) }
57
55
  end
58
56
 
59
57
  def presenter_factory_arguments
@@ -154,9 +154,9 @@ module Hyrax
154
154
  def grouped_presenters(filtered_by: nil, except: nil)
155
155
  # TODO: we probably need to retain collection_presenters (as parent_presenters)
156
156
  # and join this with member_of_collection_presenters
157
- grouped = member_of_collection_presenters.group_by(&:model_name).transform_keys { |key| key.to_s.underscore }
158
- grouped.select! { |obj| obj.downcase == filtered_by } unless filtered_by.nil?
159
- grouped.except!(*except) unless except.nil?
157
+ grouped = member_of_collection_presenters.group_by(&:model_name).transform_keys(&:human)
158
+ grouped.select! { |obj| obj.casecmp(filtered_by).zero? } unless filtered_by.nil?
159
+ grouped.reject! { |obj| except.map(&:downcase).include? obj.downcase } unless except.nil?
160
160
  grouped
161
161
  end
162
162
 
@@ -200,13 +200,14 @@ module Hyrax
200
200
 
201
201
  private
202
202
 
203
+ ##
204
+ # Returns the identifier used by ACLs to identify agents.
205
+ #
206
+ # This defaults to the `:agent_key`, but if that method doesn’t exist,
207
+ # `:user_key` will be used as a fallback.
203
208
  def id_for(agent:)
204
- case agent
205
- when Hyrax::Group
206
- "#{Hyrax::Group.name_prefix}#{agent.name}"
207
- else
208
- agent.user_key.to_s
209
- end
209
+ key = agent.try(:agent_key) || agent.user_key
210
+ key.to_s
210
211
  end
211
212
  end
212
213
 
@@ -60,7 +60,7 @@ module Hyrax
60
60
  object = ActiveFedora::Base.find(id)
61
61
  parent_ids = object.try(:member_of_collection_ids) || []
62
62
 
63
- # note: we do not yield when the object has parents. Calling the nested indexer for the
63
+ # NOTE: we do not yield when the object has parents. Calling the nested indexer for the
64
64
  # top id will reindex all descendants as well.
65
65
  if object.try(:use_nested_reindexing?)
66
66
  yield(id, parent_ids) if parent_ids.empty?
@@ -119,11 +119,11 @@ module Hyrax
119
119
  # @yield Samvera::NestingIndexer::Documents::IndexDocument
120
120
  #
121
121
  # @return [void]
122
- def self.each_child_document_of(document:, extent:, &block)
122
+ def self.each_child_document_of(document:, extent:, &block) # rubocop:disable Lint/UnusedMethodArgument
123
123
  raw_child_solr_documents_of(parent_document: document).each do |solr_document|
124
124
  child_document = coerce_solr_document_to_index_document(original_solr_document: solr_document, id: solr_document.fetch('id'))
125
125
  # during light reindexing, we want to reindex the child only if fields aren't already there
126
- block.call(child_document) if full_reindex?(extent: extent) || child_document.pathnames.empty?
126
+ yield(child_document) if full_reindex?(extent: extent) || child_document.pathnames.empty?
127
127
  end
128
128
  end
129
129
 
@@ -91,11 +91,9 @@ class Hyrax::Characterization::ValkyrieCharacterizationService
91
91
  h = {}
92
92
 
93
93
  doc.class.terminology.terms.each_pair do |key, _target|
94
- begin
95
- h[key] = doc.public_send(key)
96
- rescue NoMethodError
97
- next
98
- end
94
+ h[key] = doc.public_send(key)
95
+ rescue NoMethodError
96
+ next
99
97
  end
100
98
 
101
99
  h.compact
@@ -83,11 +83,9 @@ module Hyrax
83
83
  def add_members(collection_id:, new_members:, user:)
84
84
  messages = []
85
85
  new_members.map do |new_member|
86
- begin
87
- add_member(collection_id: collection_id, new_member: new_member, user: user)
88
- rescue Hyrax::SingleMembershipError => err
89
- messages += [err.message]
90
- end
86
+ add_member(collection_id: collection_id, new_member: new_member, user: user)
87
+ rescue Hyrax::SingleMembershipError => err
88
+ messages += [err.message]
91
89
  end
92
90
  raise Hyrax::SingleMembershipError, messages if messages.present?
93
91
  end
@@ -5,6 +5,17 @@ module Hyrax
5
5
  ##
6
6
  # Listens for events related to {Hyrax::FileMetadata}
7
7
  class FileMetadataListener
8
+ ##
9
+ # Called when 'file.characterized' event is published;
10
+ # allows post-characterization handling, like derivatives generation.
11
+ #
12
+ # @param [Dry::Events::Event] event
13
+ # @return [void]
14
+ def on_file_characterized(event)
15
+ CreateDerivativesJob
16
+ .perform_later(event[:file_set], event[:file_id], event[:path_hint])
17
+ end
18
+
8
19
  ##
9
20
  # Called when 'file.metadata.updated' event is published; reindexes a
10
21
  # {Hyrax::FileSet} when a file claiming to be its `pcdm_use:OriginalFile`
@@ -13,15 +13,13 @@ module Hyrax
13
13
  return if event[:object].is_a?(ActiveFedora::Base) # handled by legacy code
14
14
 
15
15
  Hyrax.custom_queries.find_child_file_sets(resource: event[:object]).each do |file_set|
16
- begin
17
- Hyrax.persister.delete(resource: file_set)
18
- Hyrax.publisher
19
- .publish('object.deleted', object: file_set, id: file_set.id, user: event[:user])
20
- rescue StandardError # we don't uncaught errors looping filesets
21
- Hyrax.logger.warn "Failed to delete #{file_set.class}:#{file_set.id} " \
22
- "during cleanup for resource: #{event[:object]}. " \
23
- 'This member may now be orphaned.'
24
- end
16
+ Hyrax.persister.delete(resource: file_set)
17
+ Hyrax.publisher
18
+ .publish('object.deleted', object: file_set, id: file_set.id, user: event[:user])
19
+ rescue StandardError # we don't uncaught errors looping filesets
20
+ Hyrax.logger.warn "Failed to delete #{file_set.class}:#{file_set.id} " \
21
+ "during cleanup for resource: #{event[:object]}. " \
22
+ 'This member may now be orphaned.'
25
23
  end
26
24
  end
27
25
 
@@ -33,15 +31,13 @@ module Hyrax
33
31
  return if event[:collection].is_a?(ActiveFedora::Base) # handled by legacy code
34
32
 
35
33
  Hyrax.custom_queries.find_members_of(collection: event[:collection]).each do |resource|
36
- begin
37
- resource.member_of_collection_ids -= [event[:collection].id]
38
- Hyrax.persister.save(resource: resource)
39
- Hyrax.publisher
40
- .publish('collection.membership.updated', collection: event[:collection], user: event[:user])
41
- rescue StandardError
42
- Hyrax.logger.warn "Failed to remove collection reference from #{work.class}:#{work.id} " \
43
- "during cleanup for collection: #{event[:collection]}. "
44
- end
34
+ resource.member_of_collection_ids -= [event[:collection].id]
35
+ Hyrax.persister.save(resource: resource)
36
+ Hyrax.publisher
37
+ .publish('collection.membership.updated', collection: event[:collection], user: event[:user])
38
+ rescue StandardError
39
+ Hyrax.logger.warn "Failed to remove collection reference from #{work.class}:#{work.id} " \
40
+ "during cleanup for collection: #{event[:collection]}. "
45
41
  end
46
42
  end
47
43
  end
@@ -21,7 +21,9 @@ module Hyrax
21
21
  # also belong to other collections of the same type.
22
22
  #
23
23
  # @return [True, String] true if no conflicts; otherwise, an error message string
24
+ # @deprecated Use #check instead; for removal in 4.0.0
24
25
  def validate
26
+ Deprecation.warn "#{self.class}##{__method__} is deprecated; use #check instead."
25
27
  return true if item.member_of_collection_ids.empty? || item.member_of_collection_ids.count <= 1
26
28
  return true unless single_membership_collection_types_exist?
27
29
 
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ class ValkyriePersistDerivatives < Hydra::Derivatives::PersistOutputFileService
4
+ # Persists a derivative using the defined Valkyrie storage adapter
5
+ #
6
+ # This Service conforms to the signature of `Hydra::Derivatives::PersistOutputFileService`.
7
+ # This service is a Valkyrized alternative to the default Hydra::Derivatives::PersistOutputFileService.
8
+ # This service will always update existing and does not do versioning of persisted files.
9
+ #
10
+ # to replace the default AF derivative pipeline, set
11
+ # ```
12
+ # Hydra::Derivatives.config.output_file_service = Hyrax::ValkyriePersistDerivatives
13
+ # Hydra::Derivatives.config.source_file_service = Hyrax::LocalFileService
14
+ # ```
15
+ #
16
+ # @param [#read] stream the derivative filestream
17
+ # @param [Hash] directives
18
+ # @option directives [String] :url a url to the file destination
19
+ def self.call(stream, directives)
20
+ filepath = URI(directives.fetch(:url)).path
21
+ fileset_id = fileset_id_from_path(filepath)
22
+ fileset = Hyrax.metadata_adapter.query_service.find_by(id: fileset_id)
23
+
24
+ # Valkyrie storage adapters will typically expect an IO-like object that
25
+ # responds to #path -- here we only have a StringIO, so some
26
+ # transformation is in order
27
+ tmpfile = Tempfile.new(fileset_id, encoding: 'ascii-8bit')
28
+ tmpfile.write stream.read
29
+
30
+ Rails.logger.debug "Uploading thumbnail for FileSet #{fileset_id} as #{filepath}"
31
+ Hyrax.config.derivatives_storage_adapter.upload(
32
+ file: tmpfile,
33
+ original_filename: filepath,
34
+ resource: fileset
35
+ )
36
+ end
37
+
38
+ # The filepath will look something like
39
+ # /app/samvera/hyrax-webapp/derivatives/95/93/tv/12/3-thumbnail.jpeg and
40
+ # we want to extract the FileSet id, which in this case would be 9593tv123
41
+ #
42
+ # @param [String] path
43
+ # @return [String]
44
+ def self.fileset_id_from_path(path)
45
+ path.sub(Hyrax.config.derivatives_path.to_s, "")
46
+ .sub(/-[^\/]+\..*$/, "")
47
+ .delete("/")
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax::ValkyrieUpload
4
+ # @param [IO] io
5
+ # @param [String] filename
6
+ # @param [Hyrax::FileSet] file_set
7
+ # @param [RDF::URI] use
8
+ # @param [User] user
9
+ #
10
+ # @see Hyrax::FileMetadata::Use
11
+ # @return [Hyrax::FileMetadata] the metadata representing the uploaded file
12
+ # rubocop:disable Metrics/MethodLength
13
+ # rubocop:disable Metrics/ParameterLists
14
+ def self.file(
15
+ filename:,
16
+ file_set:,
17
+ io:,
18
+ storage_adapter: Hyrax.storage_adapter,
19
+ use: Hyrax::FileMetadata::Use::ORIGINAL_FILE,
20
+ user: nil
21
+ )
22
+
23
+ streamfile = storage_adapter.upload(
24
+ file: io,
25
+ original_filename: filename,
26
+ resource: file_set,
27
+ use: use
28
+ )
29
+ io.close
30
+
31
+ file_metadata = Hyrax::FileMetadata(streamfile)
32
+ file_metadata.file_set_id = file_set.id
33
+
34
+ case use
35
+ when Hyrax::FileMetadata::Use::ORIGINAL_FILE
36
+ # Set file set label.
37
+ reset_title = file_set.title.first == file_set.label
38
+ # set title to label if that's how it was before this characterization
39
+ file_set.title = file_metadata.original_filename if reset_title
40
+ # always set the label to the original_name
41
+ file_set.label = file_metadata.original_filename
42
+ when Hyrax::FileMetadata::Use::THUMBNAIL
43
+ # TODO: the parent work's thumbnail_id remains incorrect (it's set to the
44
+ # FileSet ID, rather than the ID of this thumbnail FileMetadata; but
45
+ # trying to update the parent attributes here doesn't seem to stick
46
+ file_set.thumbnail_id = file_metadata.id
47
+ end
48
+
49
+ saved_metadata = Hyrax.persister.save(resource: file_metadata)
50
+ Hyrax.publisher.publish("object.file.uploaded", metadata: saved_metadata)
51
+
52
+ add_file_to_file_set(file_set: file_set,
53
+ file_metadata: saved_metadata,
54
+ user: user)
55
+
56
+ Hyrax.publisher.publish('file.metadata.updated', metadata: saved_metadata, user: user)
57
+
58
+ saved_metadata
59
+ end
60
+
61
+ # @param [Hyrax::FileSet] file_set the file set to add to
62
+ # @param [Hyrax::FileMetadata] file_metadata the metadata object representing
63
+ # the file to add
64
+ # @param [::User] user the user performing the add
65
+ #
66
+ # @return [Hyrax::FileSet] updated file set
67
+ def self.add_file_to_file_set(file_set:, file_metadata:, user:)
68
+ file_set.file_ids << file_metadata.id
69
+ set_file_use_ids(file_set, file_metadata)
70
+
71
+ Hyrax.persister.save(resource: file_set)
72
+ Hyrax.publisher.publish('object.membership.updated', object: file_set, user: user)
73
+ end
74
+
75
+ # @api private
76
+ # @param [Hyrax::FileSet] file_set the file set to add to
77
+ # @param [Hyrax::FileMetadata] file_metadata the metadata object representing
78
+ # the file to add
79
+ # @return [void]
80
+ def self.set_file_use_ids(file_set, file_metadata)
81
+ file_metadata.type.each do |type|
82
+ case type
83
+ when Hyrax::FileMetadata::Use::ORIGINAL_FILE
84
+ file_set.original_file_id = file_metadata.id
85
+ when Hyrax::FileMetadata::Use::THUMBNAIL
86
+ file_set.thumbnail_id = file_metadata.id
87
+ when Hyrax::FileMetadata::Use::EXTRACTED_TEXT
88
+ file_set.extracted_text_id = file_metadata.id
89
+ else
90
+ Rails.logger.warn "Unknown file use #{file_metadata.type} specified for #{file_metadata.file_identifier}"
91
+ end
92
+ end
93
+ end
94
+ end
@@ -128,16 +128,14 @@ module Hyrax
128
128
  def call
129
129
  self.errors = []
130
130
  Array.wrap(data.fetch(:workflows)).map do |configuration|
131
- begin
132
- find_or_create_from(configuration: configuration)
133
- rescue InvalidStateRemovalException => e
134
- e.states.each do |state|
135
- error = I18n.t('hyrax.workflow.load.state_error', workflow_name: state.workflow.name, state_name: state.name, entity_count: state.entities.count)
136
- Rails.logger.error(error)
137
- errors << error
138
- end
139
- Sipity::Workflow.find_by(name: configuration[:name])
131
+ find_or_create_from(configuration: configuration)
132
+ rescue InvalidStateRemovalException => e
133
+ e.states.each do |state|
134
+ error = I18n.t('hyrax.workflow.load.state_error', workflow_name: state.workflow.name, state_name: state.name, entity_count: state.entities.count)
135
+ Rails.logger.error(error)
136
+ errors << error
140
137
  end
138
+ Sipity::Workflow.find_by(name: configuration[:name])
141
139
  end
142
140
  end
143
141
 
@@ -20,11 +20,9 @@ module Hyrax
20
20
  include Dry::Types()
21
21
 
22
22
  Constant = Types::Class.constructor do |v|
23
- begin
24
- v.constantize
25
- rescue NameError => _err
26
- v
27
- end
23
+ v.constantize
24
+ rescue NameError => _err
25
+ v
28
26
  end
29
27
  end
30
28
 
@@ -34,12 +34,10 @@ module Hyrax::Strategies
34
34
 
35
35
  def yaml_file
36
36
  @yaml_file ||=
37
- begin
38
- if File.exist?(@config_file)
39
- YAML.load_file(@config_file)
40
- else
41
- {}
42
- end
37
+ if File.exist?(@config_file)
38
+ YAML.load_file(@config_file)
39
+ else
40
+ {}
43
41
  end
44
42
  end
45
43
  end
@@ -4,21 +4,21 @@ module Hyrax
4
4
  # Override the directory where uploaded files will be stored.
5
5
  # This is a sensible default for uploaders that are meant to be mounted:
6
6
  def store_dir
7
- configured_upload_path + "#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
7
+ (configured_upload_path / model.class.to_s.underscore / mounted_as.to_s / model.id.to_s).to_s
8
8
  end
9
9
 
10
10
  def cache_dir
11
- configured_cache_path + "#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
11
+ (configured_cache_path / model.class.to_s.underscore / mounted_as.to_s / model.id.to_s).to_s
12
12
  end
13
13
 
14
14
  private
15
15
 
16
16
  def configured_upload_path
17
- Hyrax.config.upload_path.call
17
+ Pathname.new(Hyrax.config.upload_path.call)
18
18
  end
19
19
 
20
20
  def configured_cache_path
21
- Hyrax.config.cache_path.call
21
+ Pathname.new(Hyrax.config.cache_path.call)
22
22
  end
23
23
  end
24
24
  end
@@ -1,30 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
  module Hyrax
3
- # Validates that the record passes the multiple membership checker
3
+ ##
4
+ # Validates that the record passes the multiple membership requirements for collections.
4
5
  class CollectionMembershipValidator < ActiveModel::Validator
5
- def validate(record)
6
- update_collections(record)
7
- validation = validate_multi_membership(record)
8
- return if validation == true
9
- record.errors[:member_of_collection_ids] << validation
6
+ ##
7
+ # @param multiple_membership_checker
8
+ def initialize(multiple_membership_checker: Hyrax::MultipleMembershipChecker, **options)
9
+ @multiple_membership_checker = multiple_membership_checker
10
+ super(options)
10
11
  end
11
12
 
12
- private
13
-
14
- def validate_multi_membership(record)
13
+ def validate(record)
15
14
  # collections-in-collections do not have multi-membership restrictions
16
15
  return true if record.is_a? Hyrax::Forms::PcdmCollectionForm
16
+ checker = @multiple_membership_checker.new(item: nil)
17
+ ids = collections_ids(record)
17
18
 
18
- Hyrax::MultipleMembershipChecker.new(item: record).validate
19
+ errors = Array(checker.check(collection_ids: ids))
20
+ record.errors[:member_of_collection_ids].concat(errors)
19
21
  end
20
22
 
21
- def update_collections(record)
22
- record.member_of_collection_ids = collections_ids(record)
23
- record.member_of_collection_ids.uniq!
24
- end
23
+ private
25
24
 
26
25
  def collections_ids(record)
27
- collection_ids = []
26
+ collection_ids = record.member_of_collection_ids.reject(&:blank?)
27
+
28
28
  if record.member_of_collections_attributes.present?
29
29
  record.member_of_collections_attributes
30
30
  .each do |_k, h|
@@ -32,6 +32,7 @@ module Hyrax
32
32
  collection_ids << Valkyrie::ID.new(h["id"])
33
33
  end
34
34
  end
35
+
35
36
  collection_ids
36
37
  end
37
38
  end
@@ -1,3 +1,10 @@
1
+ <% model = document.hydra_model %>
1
2
  <div class="search-results-title-row">
2
- <h3 class="search-result-title"><%= link_to document.title_or_label, document %></h3>
3
+ <% if model == Hyrax::PcdmCollection || model < Hyrax::PcdmCollection %>
4
+ <h3 class="search-result-title"><%= link_to document.title_or_label, [hyrax, document] %></h3>
5
+ <%= Hyrax::CollectionPresenter.new(document, current_ability).collection_type_badge %>
6
+ <% else %>
7
+ <h3 class="search-result-title"><%= link_to document.title_or_label, document %></h3>
8
+ <% end %>
3
9
  </div>
10
+
@@ -1,5 +1,10 @@
1
+ <% model = document.hydra_model %>
1
2
  <div class="col-md-2">
2
- <div class="list-thumbnail">
3
- <%= render_thumbnail_tag document %>
4
- </div>
3
+ <% if model == Hyrax::PcdmCollection || model < Hyrax::PcdmCollection %>
4
+ <%= render_thumbnail_tag document, {}, suppress_link: true %>
5
+ <% else %>
6
+ <div class="list-thumbnail">
7
+ <%= render_thumbnail_tag document %>
8
+ </div>
9
+ <% end %>
5
10
  </div>
@@ -1,8 +1,8 @@
1
1
  <%= f.input key,
2
- as: :multi_value,
3
- input_html: {
4
- class: 'form-control',
5
- data: { 'autocomplete-url' => "/authorities/search/geonames",
6
- 'autocomplete' => key }
7
- },
8
- required: f.object.required?(key) %>
2
+ as: :multi_value,
3
+ input_html: {
4
+ class: 'form-control',
5
+ data: { 'autocomplete-url' => "/authorities/search/geonames",
6
+ 'autocomplete' => key }
7
+ },
8
+ required: f.object.required?(key) %>