hyrax 4.0.0.beta2 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +66 -54
  3. data/.dassie/Gemfile +1 -1
  4. data/.dassie/app/controllers/catalog_controller.rb +1 -1
  5. data/.dassie/config/initializers/hyrax.rb +4 -0
  6. data/.github/SUPPORT.md +2 -3
  7. data/.github/workflows/main.yml +4 -4
  8. data/.github/workflows/release.yml +10 -4
  9. data/.koppie/Gemfile +1 -2
  10. data/.koppie/app/controllers/catalog_controller.rb +1 -1
  11. data/.koppie/config/authorities/licenses.yml +7 -7
  12. data/.koppie/config/initializers/file_services.rb +4 -0
  13. data/.koppie/db/schema.rb +2 -2
  14. data/.koppie/yarn.lock +1 -1
  15. data/CONTAINERS.md +2 -2
  16. data/CONTRIBUTING.md +2 -2
  17. data/Dockerfile +21 -9
  18. data/README.md +24 -97
  19. data/app/assets/stylesheets/hyrax/_catalog.scss +4 -0
  20. data/app/assets/stylesheets/hyrax/_forms.scss +4 -0
  21. data/app/controllers/concerns/hyrax/controller.rb +1 -23
  22. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +1 -0
  23. data/app/controllers/hyrax/dashboard/collections_controller.rb +1 -1
  24. data/app/controllers/hyrax/downloads_controller.rb +16 -1
  25. data/app/controllers/hyrax/file_sets_controller.rb +9 -2
  26. data/app/controllers/hyrax/my/works_controller.rb +3 -1
  27. data/app/controllers/hyrax/transfers_controller.rb +4 -1
  28. data/app/controllers/hyrax/workflow_actions_controller.rb +3 -2
  29. data/app/forms/hyrax/forms/file_set_edit_form.rb +1 -1
  30. data/app/forms/hyrax/forms/file_set_form.rb +8 -35
  31. data/app/forms/hyrax/forms/pcdm_object_form.rb +46 -0
  32. data/app/forms/hyrax/forms/resource_form.rb +9 -34
  33. data/app/helpers/hyrax/hyrax_helper_behavior.rb +1 -1
  34. data/app/indexers/hyrax/valkyrie_file_set_indexer.rb +1 -1
  35. data/app/jobs/characterize_job.rb +3 -2
  36. data/app/jobs/valkyrie_create_derivatives_job.rb +0 -2
  37. data/app/models/concerns/hyrax/ability.rb +1 -1
  38. data/app/models/concerns/hyrax/collection_behavior.rb +0 -47
  39. data/app/models/concerns/hyrax/solr_document/metadata.rb +1 -0
  40. data/app/models/concerns/hyrax/suppressible.rb +0 -8
  41. data/app/models/file_download_stat.rb +4 -4
  42. data/app/models/hyrax/collection_type.rb +0 -16
  43. data/app/models/hyrax/file_metadata.rb +5 -12
  44. data/app/models/hyrax/file_set.rb +1 -9
  45. data/app/models/hyrax/statistic.rb +4 -4
  46. data/app/models/sipity.rb +27 -6
  47. data/app/presenters/hyrax/collection_presenter.rb +1 -1
  48. data/app/presenters/hyrax/iiif_manifest_presenter.rb +14 -4
  49. data/app/presenters/hyrax/work_show_presenter.rb +1 -1
  50. data/app/presenters/hyrax/workflow_presenter.rb +1 -1
  51. data/app/search_builders/hyrax/collection_search_builder.rb +1 -0
  52. data/app/search_builders/hyrax/filter_suppressed_with_roles.rb +1 -1
  53. data/app/services/hyrax/admin_set_service.rb +1 -1
  54. data/app/services/hyrax/collections/nested_collection_query_service.rb +2 -2
  55. data/app/services/hyrax/database_migrator.rb +1 -1
  56. data/app/services/hyrax/edit_permissions_service.rb +21 -3
  57. data/app/services/hyrax/restriction_service.rb +1 -1
  58. data/app/services/hyrax/solr_query_service.rb +10 -2
  59. data/app/services/hyrax/solr_service.rb +22 -16
  60. data/app/services/hyrax/thumbnail_path_service.rb +10 -2
  61. data/app/services/hyrax/valkyrie_persist_derivatives.rb +26 -15
  62. data/app/services/hyrax/valkyrie_upload.rb +23 -30
  63. data/app/services/hyrax/visibility_propagator.rb +5 -5
  64. data/app/services/hyrax/workflow/status_list_service.rb +1 -1
  65. data/app/views/hyrax/base/_attribute_rows.html.erb +2 -0
  66. data/app/views/hyrax/dashboard/collections/_form_for_select_collection.html.erb +1 -1
  67. data/app/views/hyrax/file_sets/_permission.html.erb +1 -1
  68. data/app/views/hyrax/file_sets/edit.html.erb +1 -1
  69. data/app/views/hyrax/file_sets/media_display/_audio.html.erb +1 -1
  70. data/app/views/hyrax/file_sets/media_display/_default.html.erb +1 -1
  71. data/app/views/hyrax/file_sets/media_display/_image.html.erb +1 -1
  72. data/app/views/hyrax/file_sets/media_display/_office_document.html.erb +1 -1
  73. data/app/views/hyrax/file_sets/media_display/_pdf.html.erb +1 -1
  74. data/app/views/hyrax/file_sets/media_display/_video.html.erb +1 -1
  75. data/app/views/hyrax/uploads/_js_templates.html.erb +8 -8
  76. data/app/views/hyrax/uploads/_js_templates_branding.html.erb +2 -2
  77. data/app/views/hyrax/users/_vitals.html.erb +4 -4
  78. data/chart/hyrax/Chart.yaml +7 -7
  79. data/chart/hyrax/README.md +5 -0
  80. data/chart/hyrax/templates/_helpers.tpl +14 -6
  81. data/chart/hyrax/templates/cron-embargo.yaml +1 -1
  82. data/chart/hyrax/templates/cron-lease.yaml +1 -1
  83. data/chart/hyrax/templates/deployment-worker.yaml +2 -2
  84. data/chart/hyrax/templates/extra-list.yaml +8 -0
  85. data/chart/hyrax/templates/secrets.yaml +3 -3
  86. data/chart/hyrax/values.yaml +22 -15
  87. data/config/locales/hyrax.de.yml +7 -7
  88. data/config/locales/hyrax.es.yml +7 -7
  89. data/config/locales/hyrax.fr.yml +8 -8
  90. data/config/locales/hyrax.it.yml +7 -7
  91. data/config/locales/hyrax.pt-BR.yml +7 -7
  92. data/config/locales/hyrax.zh.yml +8 -8
  93. data/config/metadata/file_set_metadata.yaml +130 -0
  94. data/documentation/MAINTENANCE.md +77 -0
  95. data/documentation/developing-your-hyrax-based-app.md +2 -2
  96. data/documentation/legacyREADME.md +2 -2
  97. data/hyrax.gemspec +4 -4
  98. data/lib/generators/hyrax/templates/catalog_controller.rb +1 -1
  99. data/lib/hyrax/configuration.rb +5 -0
  100. data/lib/hyrax/engine.rb +0 -1
  101. data/lib/hyrax/transactions/container.rb +0 -2
  102. data/lib/hyrax/transactions/steps/save_collection_banner.rb +1 -1
  103. data/lib/hyrax/transactions/steps/save_collection_logo.rb +1 -1
  104. data/lib/hyrax/version.rb +1 -1
  105. data/lib/valkyrie/indexing/solr/indexing_adapter.rb +1 -1
  106. data/lib/wings/active_fedora_converter/file_metadata_node.rb +1 -1
  107. data/samvera-fall-TM3.svg +376 -0
  108. data/template.rb +1 -1
  109. metadata +36 -45
  110. data/app/conversions/power_converters/polymorphic_type.rb +0 -9
  111. data/app/conversions/power_converters/sipity_action.rb +0 -11
  112. data/app/conversions/power_converters/sipity_action_name.rb +0 -10
  113. data/app/conversions/power_converters/sipity_agent.rb +0 -9
  114. data/app/conversions/power_converters/sipity_entity.rb +0 -14
  115. data/app/conversions/power_converters/sipity_role.rb +0 -10
  116. data/app/conversions/power_converters/sipity_workflow_id.rb +0 -17
  117. data/app/conversions/power_converters/sipity_workflow_state.rb +0 -13
  118. data/app/conversions/power_converters.rb +0 -7
@@ -52,25 +52,6 @@ module Hyrax
52
52
  self.collection_type_gid = new_collection_type.to_global_id
53
53
  end
54
54
 
55
- # Add members using the members association.
56
- def add_members(new_member_ids)
57
- Deprecation.warn("'##{__method__}' will be removed in Hyrax 4.0. " \
58
- "Instead, use Hyrax::Collections::CollectionMemberService.add_members_by_ids.")
59
- Hyrax::Collections::CollectionMemberService.add_members_by_ids(collection_id: id,
60
- new_member_ids: new_member_ids,
61
- user: nil)
62
- end
63
-
64
- # Add member objects by adding this collection to the objects' member_of_collection association.
65
- # @param [Enumerable<String>] the ids of the new child collections and works collection ids
66
- def add_member_objects(new_member_ids)
67
- Deprecation.warn("'##{__method__}' will be removed in Hyrax 4.0. " \
68
- "Instead, use Hyrax::Collections::CollectionMemberService.add_members_by_ids.")
69
- Hyrax::Collections::CollectionMemberService.add_members_by_ids(collection_id: id,
70
- new_member_ids: new_member_ids,
71
- user: nil)
72
- end
73
-
74
55
  # @return [Enumerable<ActiveFedora::Base>] an enumerable over the children of this collection
75
56
  def member_objects
76
57
  ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id}")
@@ -96,22 +77,6 @@ module Hyrax
96
77
  "hyrax/#{collection}/#{element}"
97
78
  end
98
79
  end
99
-
100
- def collection_type_gid_document_field_name
101
- Deprecation.warn('use Hyrax.config.collection_type_index_field instead')
102
- Hyrax.config.collection_type_index_field
103
- end
104
- end
105
-
106
- # @deprecated to be removed in 4.0.0; this feature was replaced with a
107
- # hard-coded null implementation
108
- # @return [Fixnum] 0
109
- def bytes
110
- Deprecation.warn('#bytes has been deprecated for removal in Hyrax 4.0.0; ' \
111
- 'The implementation of the indexed Collection size ' \
112
- 'feature is extremely inefficient, so it has been removed. ' \
113
- 'This method now returns a hard-coded `0` for compatibility.')
114
- 0
115
80
  end
116
81
 
117
82
  # @api public
@@ -122,18 +87,6 @@ module Hyrax
122
87
  Hyrax::PermissionTemplate.find_by!(source_id: id)
123
88
  end
124
89
 
125
- ##
126
- # @deprecated use PermissionTemplate#reset_access_controls_for instead
127
- #
128
- # Calculate and update who should have read/edit access to the collections based on who
129
- # has access in PermissionTemplateAccess
130
- def reset_access_controls!
131
- Deprecation.warn("reset_access_controls! is deprecated; use PermissionTemplate#reset_access_controls_for instead.")
132
-
133
- permission_template
134
- .reset_access_controls_for(collection: self, interpret_visibility: true)
135
- end
136
-
137
90
  private
138
91
 
139
92
  # Solr field name works use to index member ids
@@ -69,6 +69,7 @@ module Hyrax
69
69
  attribute :date_created, Solr::Array, "date_created_tesim"
70
70
  attribute :rights_statement, Solr::Array, "rights_statement_tesim"
71
71
  attribute :rights_notes, Solr::Array, "rights_notes_tesim"
72
+ attribute :bibliographic_citation, Solr::Array, "bibliographic_citation_tesim"
72
73
  attribute :access_right, Solr::Array, "access_right_tesim"
73
74
  attribute :mime_type, Solr::String, "mime_type_ssi"
74
75
  attribute :workflow_state, Solr::String, "workflow_state_name_ssim"
@@ -22,13 +22,5 @@ module Hyrax
22
22
  def suppressed?
23
23
  Hyrax::ResourceStatus.new(resource: self).inactive?
24
24
  end
25
-
26
- ##
27
- # @deprecated Use `Sipity::Entity(entity)` instead.
28
- def to_sipity_entity
29
- Deprecation.warn "Use `Sipity::Entity(entity)` instead."
30
- raise "Can't create an entity until the model has been persisted" unless persisted?
31
- @sipity_entity ||= Sipity::Entity(to_global_id)
32
- end
33
25
  end
34
26
  end
@@ -12,10 +12,10 @@ class FileDownloadStat < Hyrax::Statistic
12
12
  Hyrax.logger.error("Google Analytics profile has not been established. Unable to fetch statistics.")
13
13
  return []
14
14
  end
15
- profile.hyrax__analytics__google__download(sort: 'date',
16
- start_date: start_date,
17
- end_date: Date.yesterday,
18
- limit: 10_000)
15
+ profile.hyrax__download(sort: 'date',
16
+ start_date: start_date,
17
+ end_date: Date.yesterday,
18
+ limit: 10_000)
19
19
  .for_file(file.id)
20
20
  end
21
21
 
@@ -36,14 +36,6 @@ module Hyrax
36
36
  assign_machine_id
37
37
  end
38
38
 
39
- # this class attribute is deprecated in favor of {.settings_attributes}
40
- # these need to carefully align with boolean flag attributes/table columns,
41
- # so making it settable is a liability. deprecating is challenging because
42
- # +class_attribute+ calls +singleton_class.class_eval { redefine_method }+
43
- # as the +name=+ implementation. there should be few callers outside hyrax.
44
- class_attribute :collection_type_settings_methods, instance_writer: false
45
- self.collection_type_settings_methods = SETTINGS_ATTRIBUTES
46
-
47
39
  # These are provided as a convenience method based on prior design discussions.
48
40
  alias_attribute :discovery, :discoverable
49
41
  alias_attribute :sharing, :sharable
@@ -123,14 +115,6 @@ module Hyrax
123
115
  ActiveFedora::Base.where(Hyrax.config.collection_type_index_field.to_sym => to_global_id.to_s)
124
116
  end
125
117
 
126
- ##
127
- # @deprecated Use #collections.any? instead
128
- #
129
- # @return [Boolean] True if there is at least one collection of this type
130
- def collections?
131
- Deprecation.warn('Use #collections.any? instead.') && collections.any?
132
- end
133
-
134
118
  # @return [Boolean] True if this is the Admin Set type
135
119
  def admin_set?
136
120
  machine_id == ADMIN_SET_MACHINE_ID
@@ -13,11 +13,13 @@ module Hyrax
13
13
  file.is_a?(Valkyrie::Resource)
14
14
 
15
15
  Hyrax.custom_queries.find_file_metadata_by(id: file.id)
16
- rescue Hyrax::ObjectNotFoundError, Ldp::BadRequest
16
+ rescue Hyrax::ObjectNotFoundError, Ldp::BadRequest, Valkyrie::Persistence::ObjectNotFoundError
17
17
  Hyrax.logger.debug('Could not find an existing metadata node for file ' \
18
18
  "with id #{file.id}. Initializing a new one")
19
19
 
20
- FileMetadata.new(file_identifier: file.id, alternative_ids: [file.id])
20
+ FileMetadata.new(file_identifier: file.id,
21
+ alternative_ids: [file.id],
22
+ original_filename: File.basename(file.io))
21
23
  end
22
24
 
23
25
  class FileMetadata < Valkyrie::Resource
@@ -65,7 +67,7 @@ module Hyrax
65
67
  attribute :label, ::Valkyrie::Types::Set
66
68
  attribute :original_filename, ::Valkyrie::Types::String
67
69
  attribute :mime_type, ::Valkyrie::Types::String.default(GENERIC_MIME_TYPE)
68
- attribute :type, ::Valkyrie::Types::Set.default([Use::ORIGINAL_FILE].freeze)
70
+ attribute :type, ::Valkyrie::Types::Set.default([Use::ORIGINAL_FILE].freeze) # Use += to add types, not <<
69
71
 
70
72
  # attributes set by fits
71
73
  attribute :format_label, ::Valkyrie::Types::Set
@@ -125,15 +127,6 @@ module Hyrax
125
127
  # attributes set by fits for video
126
128
  attribute :aspect_ratio, ::Valkyrie::Types::Set
127
129
 
128
- # @param [ActionDispatch::Http::UploadedFile] file
129
- # @deprecated Use #new instead; for removal in 4.0.0
130
- def self.for(file:)
131
- Deprecation.warn "#{self.class}##{__method__} is deprecated; use #new instead."
132
- new(label: file.original_filename,
133
- original_filename: file.original_filename,
134
- mime_type: file.content_type)
135
- end
136
-
137
130
  ##
138
131
  # @return [Boolean]
139
132
  def original_file?
@@ -31,7 +31,7 @@ module Hyrax
31
31
  # @see https://wiki.duraspace.org/display/samvera/Hydra%3A%3AWorks+Shared+Modeling
32
32
  class FileSet < Hyrax::Resource
33
33
  include Hyrax::Schema(:core_metadata)
34
- include Hyrax::Schema(:basic_metadata)
34
+ include Hyrax::Schema(:file_set_metadata)
35
35
 
36
36
  def self.model_name(name_class: Hyrax::Name)
37
37
  @_model_name ||= name_class.new(self, nil, 'FileSet')
@@ -51,14 +51,6 @@ module Hyrax
51
51
  id
52
52
  end
53
53
 
54
- ##
55
- # @return [Valkyrie::ID]
56
- # If one is set then return it, otherwise use self as the ID to allow for
57
- # derivative generators to find the on-disk path for the thumbnail.
58
- def thumbnail_id
59
- self.[](:thumbnail_id) || id
60
- end
61
-
62
54
  ##
63
55
  # @return [Boolean] true
64
56
  def pcdm_object?
@@ -34,10 +34,10 @@ module Hyrax
34
34
  Hyrax.logger.error("Google Analytics profile has not been established. Unable to fetch statistics.")
35
35
  return []
36
36
  end
37
- profile.hyrax__analytics__google__pageviews(sort: 'date',
38
- start_date: start_date,
39
- end_date: Date.yesterday,
40
- limit: 10_000)
37
+ profile.hyrax__pageview(sort: 'date',
38
+ start_date: start_date,
39
+ end_date: Date.yesterday,
40
+ limit: 10_000)
41
41
  .for_path(path)
42
42
  end
43
43
 
data/app/models/sipity.rb CHANGED
@@ -104,10 +104,33 @@ module Sipity
104
104
  end
105
105
  module_function :Role
106
106
 
107
+ ##
108
+ # Cast an object to a Workflow id
109
+ # rubocop:disable Metrics/MethodLength
110
+ def WorkflowId(input, &block) # rubocop:disable Naming/MethodName
111
+ result = case input
112
+ when Sipity::Workflow
113
+ input.id
114
+ when Integer
115
+ input
116
+ when String
117
+ input.to_i
118
+ else
119
+ if input.respond_to?(workflow_id)
120
+ input.workflow_id
121
+ else
122
+ WorkflowId(Entity(input))
123
+ end
124
+ end
125
+ handle_conversion(input, result, :to_workflow_id, &block)
126
+ end
127
+ module_function :WorkflowId
128
+ # rubocop:enable Metrics/MethodLength
129
+
107
130
  ##
108
131
  # Cast an object to a WorkflowAction in a given workflow
109
132
  def WorkflowAction(input, workflow, &block) # rubocop:disable Naming/MethodName
110
- workflow_id = PowerConverter.convert_to_sipity_workflow_id(workflow)
133
+ workflow_id = WorkflowId(workflow)
111
134
 
112
135
  result = case input
113
136
  when WorkflowAction
@@ -138,11 +161,9 @@ module Sipity
138
161
  # A parent error class for all workflow errors caused by bad state
139
162
  class StateError < RuntimeError; end
140
163
 
141
- class ConversionError < PowerConverter::ConversionError
142
- def initialize(value, **options)
143
- options[:scope] ||= nil
144
- options[:to] ||= nil
145
- super(value, options)
164
+ class ConversionError < RuntimeError
165
+ def initialize(value)
166
+ super("Unable to convert #{value.inspect}")
146
167
  end
147
168
  end
148
169
 
@@ -43,7 +43,7 @@ module Hyrax
43
43
  # Terms is the list of fields displayed by
44
44
  # app/views/collections/_show_descriptions.html.erb
45
45
  def self.terms
46
- [:total_items, :size, :resource_type, :creator, :contributor, :keyword, :license, :publisher, :date_created, :subject,
46
+ [:total_items, :alternative_title, :size, :resource_type, :creator, :contributor, :keyword, :license, :publisher, :date_created, :subject,
47
47
  :language, :identifier, :based_near, :related_url]
48
48
  end
49
49
 
@@ -47,6 +47,12 @@ module Hyrax
47
47
  Array(super).first || ''
48
48
  end
49
49
 
50
+ ##
51
+ # @return [String]
52
+ def hostname
53
+ @hostname || 'localhost'
54
+ end
55
+
50
56
  ##
51
57
  # @return [Boolean]
52
58
  def file_set?
@@ -209,6 +215,14 @@ module Hyrax
209
215
  iiif_endpoint: iiif_endpoint(latest_file_id, base_url: hostname))
210
216
  end
211
217
 
218
+ ##
219
+ # @return [#can?]
220
+ def ability
221
+ @ability ||= NullAbility.new
222
+ end
223
+
224
+ ##
225
+ # @return [String]
212
226
  def hostname
213
227
  @hostname || 'localhost'
214
228
  end
@@ -222,10 +236,6 @@ module Hyrax
222
236
 
223
237
  private
224
238
 
225
- def hostname
226
- @hostname || 'localhost'
227
- end
228
-
229
239
  def metadata_fields
230
240
  Hyrax.config.iiif_metadata_fields
231
241
  end
@@ -45,7 +45,7 @@ module Hyrax
45
45
  delegate :title, :date_created, :description,
46
46
  :creator, :contributor, :subject, :publisher, :language, :embargo_release_date,
47
47
  :lease_expiration_date, :license, :source, :rights_statement, :thumbnail_id, :representative_id,
48
- :rendering_ids, :member_of_collection_ids, :alternative_title, to: :solr_document
48
+ :rendering_ids, :member_of_collection_ids, :alternative_title, :bibliographic_citation, to: :solr_document
49
49
 
50
50
  def workflow
51
51
  @workflow ||= WorkflowPresenter.new(solr_document, current_ability)
@@ -44,7 +44,7 @@ module Hyrax
44
44
 
45
45
  def sipity_entity
46
46
  Sipity::Entity(solr_document)
47
- rescue PowerConverter::ConversionError
47
+ rescue Sipity::ConversionError
48
48
  nil
49
49
  end
50
50
  end
@@ -37,6 +37,7 @@ module Hyrax
37
37
  # This overrides the default 'relevance' sort.
38
38
  def add_sorting_to_solr(solr_parameters)
39
39
  return if solr_parameters[:q]
40
+ solr_parameters[:sort] ||= sort
40
41
  solr_parameters[:sort] ||= "#{sort_field} asc"
41
42
  end
42
43
 
@@ -32,7 +32,7 @@ module Hyrax
32
32
 
33
33
  def user_has_active_workflow_role?(current_work:)
34
34
  Hyrax::Workflow::PermissionQuery.scope_permitted_workflow_actions_available_for_current_state(user: current_ability.current_user, entity: current_work).any?
35
- rescue PowerConverter::ConversionError
35
+ rescue Sipity::ConversionError
36
36
  # The current_work doesn't have a sipity workflow entity
37
37
  false
38
38
  end
@@ -15,7 +15,7 @@ module Hyrax
15
15
 
16
16
  # @param [Symbol] access :deposit, :read or :edit
17
17
  def search_results(access)
18
- response = context.repository.search(builder(access))
18
+ response = context.blacklight_config.repository.search(builder(access))
19
19
  response.documents
20
20
  end
21
21
 
@@ -51,7 +51,7 @@ module Hyrax
51
51
  def self.parent_collections(child:, scope:, page: 1)
52
52
  return [] unless nestable?(collection: child)
53
53
  query_builder = Hyrax::NestedCollectionsParentSearchBuilder.new(scope: scope, child: child, page: page)
54
- scope.repository.search(query_builder.query)
54
+ scope.blacklight_config.repository.search(query_builder.query)
55
55
  end
56
56
 
57
57
  ##
@@ -73,7 +73,7 @@ module Hyrax
73
73
  )
74
74
 
75
75
  query_builder.where(id: limit_to_id.to_s) if limit_to_id
76
- scope.repository.search(query_builder.query)
76
+ scope.blacklight_config.repository.search(query_builder.query)
77
77
  end
78
78
  private_class_method :query_solr
79
79
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'rails/generators/actions'
2
+ require 'rails/generators'
3
3
  require 'rails/generators/active_record'
4
4
 
5
5
  module Hyrax
@@ -20,17 +20,35 @@ module Hyrax
20
20
  # @note
21
21
  # +form object.class = SimpleForm::FormBuilder+
22
22
  # For works (i.e. GenericWork):
23
- # * form object.object = Hyrax::GenericWorkForm
24
- # * form object.object.model = GenericWork
23
+ # * form_object.object = Hyrax::GenericWorkForm
24
+ # * form_object.object.model = GenericWork
25
25
  # * use the work itself
26
26
  # For file_sets:
27
- # * form object.object.class = FileSet
27
+ # * form_object.object.class = FileSet
28
+ # * use work the file_set is in
29
+ # For file set forms:
30
+ # * form_object.object.class = Hyrax::Forms::FileSetForm OR
31
+ # Hyrax::Forms::FileSetEditForm
32
+ # * form_object.object.model = FileSet
28
33
  # * use work the file_set is in
29
34
  # No other object types are supported by this view.
30
35
  def self.build_service_object_from(form:, ability:)
31
36
  if form.object.respond_to?(:model) && form.object.model.work?
37
+ # The provided form object is a work form.
32
38
  new(object: form.object, ability: ability)
39
+ elsif form.object.respond_to?(:model) && form.object.model.file_set?
40
+ # The provided form object is a FileSet form. For Valkyrie forms
41
+ # (+Hyrax::Forms::FileSetForm+), +:in_works_ids+ is prepopulated onto
42
+ # the form object itself. For +Hyrax::Forms::FileSetEditForm+, the
43
+ # +:in_works+ method is present on the wrapped +:model+.
44
+ if form.object.is_a?(Hyrax::Forms::FileSetForm)
45
+ object_id = form.object.in_works_ids.first
46
+ new(object: Hyrax.query_service.find_by(id: object_id), ability: ability)
47
+ else
48
+ new(object: form.object.model.in_works.first, ability: ability)
49
+ end
33
50
  elsif form.object.file_set?
51
+ # The provided form object is a FileSet.
34
52
  new(object: form.object.in_works.first, ability: ability)
35
53
  end
36
54
  end
@@ -18,7 +18,7 @@ module Hyrax
18
18
  end
19
19
 
20
20
  def repository
21
- config.repository
21
+ config.blacklight_config.repository
22
22
  end
23
23
 
24
24
  def config
@@ -26,21 +26,29 @@ module Hyrax
26
26
  end
27
27
 
28
28
  ##
29
+ # execute the query using a GET request
29
30
  # @return [Hash] the results returned from solr for the current query
30
31
  def get
31
32
  solr_service.get(build)
32
33
  end
33
34
 
35
+ ##
36
+ # execute the solr query and return results
37
+ # @return [Hash] the results returned from solr for the current query
38
+ def query_result
39
+ solr_service.query_result(build)
40
+ end
41
+
34
42
  ##
35
43
  # @return [Enumerable<SolrDocument>]
36
44
  def solr_documents
37
- get['response']['docs'].map { |doc| self.class.document_model.new(doc) }
45
+ query_result['response']['docs'].map { |doc| self.class.document_model.new(doc) }
38
46
  end
39
47
 
40
48
  ##
41
49
  # @return [Array<String>] ids of documents matching the current query
42
50
  def get_ids # rubocop:disable Naming/AccessorMethodName
43
- results = get
51
+ results = query_result
44
52
  results['response']['docs'].map { |doc| doc['id'] }
45
53
  end
46
54
 
@@ -38,7 +38,7 @@ module Hyrax
38
38
  end
39
39
 
40
40
  delegate :add, :commit, :count, :delete, :get, :instance, :ping, :post,
41
- :query, :delete_by_query, :search_by_id, :wipe!, to: :new
41
+ :query, :query_result, :delete_by_query, :search_by_id, :wipe!, to: :new
42
42
  end
43
43
 
44
44
  # Wraps rsolr get
@@ -72,21 +72,27 @@ module Hyrax
72
72
  connection.post(solr_path, data: args)
73
73
  end
74
74
 
75
- # Wraps get by default
75
+ # Query solr using the provided or default http method, returning the result as a hash.
76
+ # @return [Hash] raw query result from solr
77
+ def query_result(query, **args)
78
+ Hyrax.logger.warn rows_warning unless args.key?(:rows)
79
+ # Use the provided solr query method, or fall back to the configured default
80
+ method = args.delete(:method) || Hyrax.config.solr_default_method
81
+
82
+ case method
83
+ when :get
84
+ get(query, **args)
85
+ when :post
86
+ post(query, **args)
87
+ else
88
+ raise "Unsupported HTTP method for querying SolrService (#{method.inspect})"
89
+ end
90
+ end
91
+
92
+ # Execute the provided query. Uses the configured http method by default.
76
93
  # @return [Array<SolrHit>] the response docs wrapped in SolrHit objects
77
94
  def query(query, **args)
78
- Hyrax.logger.warn rows_warning unless args.key?(:rows)
79
- method = args.delete(:method) || :get
80
-
81
- result = case method
82
- when :get
83
- get(query, **args)
84
- when :post
85
- post(query, **args)
86
- else
87
- raise "Unsupported HTTP method for querying SolrService (#{method.inspect})"
88
- end
89
- result['response']['docs'].map do |doc|
95
+ query_result(query, **args)['response']['docs'].map do |doc|
90
96
  ::SolrHit.new(doc)
91
97
  end
92
98
  end
@@ -114,10 +120,10 @@ module Hyrax
114
120
  end
115
121
 
116
122
  # Wraps rsolr count
117
- # @return [Hash] the hash straight form rsolr
123
+ # @return [Hash] the hash straight from rsolr
118
124
  def count(query)
119
125
  args = { rows: 0 }
120
- get(query, **args)['response']['numFound'].to_i
126
+ query_result(query, **args)['response']['numFound'].to_i
121
127
  end
122
128
 
123
129
  # Wraps ActiveFedora::Base#search_by_id(id, opts)
@@ -28,7 +28,8 @@ module Hyrax
28
28
  end
29
29
 
30
30
  def fetch_thumbnail(object)
31
- return object if object.thumbnail_id == object.id
31
+ return object if object.thumbnail_id == object.id ||
32
+ object.try(:file_ids)&.detect { |fid| fid == object.thumbnail_id }
32
33
  Hyrax.query_service.find_by_alternate_identifier(alternate_identifier: object.thumbnail_id)
33
34
  rescue Valkyrie::Persistence::ObjectNotFoundError, Hyrax::ObjectNotFoundError
34
35
  Hyrax.logger.error("Couldn't find thumbnail #{object.thumbnail_id} for #{object.id}")
@@ -53,13 +54,20 @@ module Hyrax
53
54
  # @return true if there a file on disk for this object, otherwise false
54
55
  # @param [FileSet] thumb - the object that is the thumbnail
55
56
  def thumbnail?(thumb)
56
- File.exist?(thumbnail_filepath(thumb))
57
+ File.exist?(thumbnail_filepath(thumb)) ||
58
+ (thumb.is_a?(Hyrax::Resource) && file_in_storage?(thumb))
57
59
  end
58
60
 
59
61
  # @param [FileSet] thumb - the object that is the thumbnail
60
62
  def thumbnail_filepath(thumb)
61
63
  Hyrax::DerivativePath.derivative_path_for_reference(thumb, 'thumbnail')
62
64
  end
65
+
66
+ def file_in_storage?(thumb)
67
+ Hyrax.custom_queries.find_thumbnail(file_set: thumb)
68
+ rescue Valkyrie::StorageAdapter::FileNotFound, Valkyrie::Persistence::ObjectNotFoundError
69
+ false
70
+ end
63
71
  end
64
72
  end
65
73
  end
@@ -16,22 +16,25 @@ module Hyrax
16
16
  # @param [#read] stream the derivative filestream
17
17
  # @param [Hash] directives
18
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)
19
+ def self.call(stream,
20
+ directives,
21
+ uploader: Hyrax::ValkyrieUpload.new(storage_adapter: Hyrax.config.derivatives_storage_adapter))
22
+ file_set = fileset_for_directives(directives)
23
23
 
24
24
  # Valkyrie storage adapters will typically expect an IO-like object that
25
25
  # responds to #path -- here we only have a StringIO, so some
26
26
  # transformation is in order
27
- tmpfile = Tempfile.new(fileset_id, encoding: 'ascii-8bit')
27
+ tmpfile = Tempfile.new(file_set.id, encoding: 'ascii-8bit')
28
28
  tmpfile.write stream.read
29
29
 
30
- Hyrax.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
30
+ filename = filename(directives)
31
+ Hyrax.logger.debug "Uploading thumbnail for FileSet #{file_set.id} as #{filename}"
32
+
33
+ uploader.upload(
34
+ io: tmpfile,
35
+ filename: filename,
36
+ file_set: file_set,
37
+ use: Hyrax::FileMetadata::Use::THUMBNAIL
35
38
  )
36
39
  end
37
40
 
@@ -40,11 +43,19 @@ module Hyrax
40
43
  # we want to extract the FileSet id, which in this case would be 9593tv123
41
44
  #
42
45
  # @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("/")
46
+ # @return [Hyrax::FileSet]
47
+ def self.fileset_for_directives(directives)
48
+ path = URI(directives.fetch(:url)).path
49
+ id = path.sub(Hyrax.config.derivatives_path.to_s, "")
50
+ .delete('/')
51
+ .match(/^(.*)-\w*(\.\w+)*$/) { |m| m[1] }
52
+ raise "Could not extract fileset id from path #{path}" unless id
53
+
54
+ Hyrax.metadata_adapter.query_service.find_by(id: id)
55
+ end
56
+
57
+ def self.filename(directives)
58
+ URI(directives.fetch(:url)).path.split('/').last
48
59
  end
49
60
  end
50
61
  end