hyrax 4.0.0 → 5.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +116 -231
  3. data/.dassie/.env +3 -1
  4. data/.dassie/config/environments/test.rb +1 -0
  5. data/.dassie/config/initializers/hyrax.rb +3 -1
  6. data/.dassie/config/initializers/riiif.rb +13 -3
  7. data/.dassie/db/schema.rb +2 -2
  8. data/.dockerignore +6 -0
  9. data/.github/PULL_REQUEST_TEMPLATE.md +10 -7
  10. data/.github/release.yml +5 -2
  11. data/.koppie/.env +3 -0
  12. data/.koppie/app/forms/collection_resource_form.rb +1 -0
  13. data/.koppie/app/indexers/collection_resource_indexer.rb +1 -0
  14. data/.koppie/app/models/collection_resource.rb +1 -0
  15. data/.koppie/config/environments/test.rb +1 -0
  16. data/.koppie/config/initializers/hyrax.rb +8 -2
  17. data/.koppie/config/initializers/riiif.rb +13 -4
  18. data/.koppie/config/metadata/collection_resource.yaml +1 -128
  19. data/.koppie/yarn.lock +23 -23
  20. data/.regen +1 -1
  21. data/CONTAINERS.md +1 -1
  22. data/Dockerfile +6 -11
  23. data/app/actors/hyrax/actors/base_actor.rb +4 -3
  24. data/app/actors/hyrax/actors/embargo_actor.rb +5 -2
  25. data/app/actors/hyrax/actors/lease_actor.rb +5 -2
  26. data/app/assets/javascripts/hyrax/file_manager/sorting.es6 +3 -2
  27. data/app/controllers/concerns/hyrax/embargoes_controller_behavior.rb +1 -1
  28. data/app/controllers/concerns/hyrax/valkyrie_downloads_controller_behavior.rb +74 -0
  29. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +14 -5
  30. data/app/controllers/hyrax/admin/workflows_controller.rb +48 -3
  31. data/app/controllers/hyrax/batch_edits_controller.rb +33 -4
  32. data/app/controllers/hyrax/downloads_controller.rb +8 -1
  33. data/app/controllers/hyrax/file_sets_controller.rb +1 -0
  34. data/app/forms/hyrax/forms/file_set_edit_form.rb +1 -1
  35. data/app/forms/hyrax/forms/permission_template_form.rb +2 -0
  36. data/app/forms/hyrax/forms/resource_batch_edit_form.rb +90 -0
  37. data/app/forms/hyrax/forms/work_embargo_form.rb +1 -0
  38. data/app/forms/hyrax/forms/work_form.rb +1 -1
  39. data/app/forms/hyrax/forms/work_lease_form.rb +1 -0
  40. data/app/helpers/hyrax/dashboard_helper_behavior.rb +17 -9
  41. data/app/helpers/hyrax/membership_helper.rb +13 -1
  42. data/app/helpers/hyrax/work_form_helper.rb +0 -107
  43. data/app/indexers/hyrax/file_set_indexer.rb +6 -0
  44. data/app/indexers/hyrax/pcdm_collection_indexer.rb +8 -0
  45. data/app/indexers/hyrax/valkyrie_file_set_indexer.rb +41 -5
  46. data/app/indexers/hyrax/valkyrie_work_indexer.rb +8 -2
  47. data/app/jobs/valkyrie_create_derivatives_job.rb +8 -7
  48. data/app/jobs/valkyrie_ingest_job.rb +0 -1
  49. data/app/models/admin_set.rb +1 -31
  50. data/app/models/concerns/hyrax/file_set/derivatives.rb +3 -2
  51. data/app/models/concerns/hyrax/solr_document_behavior.rb +1 -1
  52. data/app/models/hyrax/collection_type.rb +5 -14
  53. data/app/models/hyrax/file_metadata.rb +6 -7
  54. data/app/models/hyrax/file_set.rb +8 -0
  55. data/app/models/hyrax/resource.rb +30 -2
  56. data/app/presenters/hyrax/file_set_presenter.rb +6 -0
  57. data/app/presenters/hyrax/iiif_manifest_presenter.rb +3 -7
  58. data/app/presenters/hyrax/presenter_renderer.rb +0 -7
  59. data/app/presenters/hyrax/work_show_presenter.rb +6 -11
  60. data/app/search_builders/hyrax/file_set_search_builder.rb +1 -1
  61. data/app/search_builders/hyrax/valkyrie_abstract_type_relation.rb +37 -0
  62. data/app/search_builders/hyrax/valkyrie_work_relation.rb +9 -0
  63. data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +11 -9
  64. data/app/services/hyrax/custom_queries/find_by_date_range.rb +55 -0
  65. data/app/services/hyrax/custom_queries/find_count_by.rb +62 -0
  66. data/app/services/hyrax/custom_queries/find_file_metadata.rb +1 -1
  67. data/app/services/hyrax/custom_queries/find_models_by_access.rb +59 -0
  68. data/app/services/hyrax/derivative_bucketed_storage.rb +25 -0
  69. data/app/services/hyrax/derivative_path.rb +14 -4
  70. data/app/services/hyrax/embargo_manager.rb +76 -10
  71. data/app/services/hyrax/file_set_derivatives_service.rb +3 -2
  72. data/app/services/hyrax/lease_manager.rb +88 -8
  73. data/app/services/hyrax/listeners/file_metadata_listener.rb +2 -2
  74. data/app/services/hyrax/listeners/workflow_listener.rb +8 -11
  75. data/app/services/hyrax/persist_directly_contained_output_file_service.rb +24 -2
  76. data/app/services/hyrax/solr_query_service.rb +7 -6
  77. data/app/services/hyrax/statistics/depositors/summary.rb +1 -1
  78. data/app/services/hyrax/statistics/over_time.rb +1 -1
  79. data/app/services/hyrax/statistics/users/over_time.rb +3 -1
  80. data/app/services/hyrax/statistics/valkyrie_query_service.rb +49 -0
  81. data/app/services/hyrax/statistics/works/count.rb +1 -1
  82. data/app/services/hyrax/thumbnail_path_service.rb +5 -0
  83. data/app/services/hyrax/valkyrie_persist_derivatives.rb +16 -11
  84. data/app/services/hyrax/valkyrie_upload.rb +5 -3
  85. data/app/services/hyrax/versioning_service.rb +1 -0
  86. data/app/services/hyrax/visibility_intention.rb +1 -4
  87. data/app/services/hyrax/visibility_propagator.rb +1 -1
  88. data/app/services/hyrax/workflow/actionable_objects.rb +28 -3
  89. data/app/services/hyrax/workflow/grant_edit_to_depositor.rb +1 -1
  90. data/app/services/hyrax/workflow/grant_read_to_depositor.rb +1 -1
  91. data/app/services/hyrax/workflow/permission_query.rb +23 -2
  92. data/app/views/hyrax/admin/workflows/_tabs.html.erb +9 -0
  93. data/app/views/hyrax/admin/workflows/index.html.erb +53 -76
  94. data/app/views/hyrax/base/_file_manager_members.html.erb +2 -2
  95. data/app/views/hyrax/base/_form.html.erb +0 -10
  96. data/app/views/hyrax/base/_form_permission_embargo.html.erb +1 -1
  97. data/app/views/hyrax/base/_form_permission_lease.html.erb +1 -1
  98. data/app/views/hyrax/base/_form_visibility_component.html.erb +2 -2
  99. data/app/views/hyrax/base/_items.html.erb +1 -1
  100. data/app/views/hyrax/base/file_manager.html.erb +1 -1
  101. data/app/views/hyrax/base/show.json.jbuilder +2 -2
  102. data/app/views/hyrax/file_sets/show.html.erb +5 -3
  103. data/app/views/hyrax/homepage/_explore_collections.html.erb +1 -1
  104. data/chart/hyrax/Chart.yaml +18 -14
  105. data/chart/hyrax/README.md +34 -21
  106. data/chart/hyrax/templates/_helpers.tpl +26 -1
  107. data/chart/hyrax/templates/configmap-env.yaml +12 -2
  108. data/chart/hyrax/templates/secrets.yaml +1 -1
  109. data/chart/hyrax/values.yaml +36 -14
  110. data/config/initializers/listeners.rb +4 -10
  111. data/config/initializers/storage_adapter_initializer.rb +1 -1
  112. data/config/locales/hyrax.en.yml +8 -0
  113. data/config/metadata/file_set_metadata.yaml +1 -1
  114. data/docker-compose-koppie.yml +17 -4
  115. data/docker-compose.yml +19 -6
  116. data/documentation/developing-your-hyrax-based-app.md +6 -14
  117. data/documentation/legacyREADME.md +3 -1
  118. data/hyrax.gemspec +2 -2
  119. data/karma.conf.js +8 -9
  120. data/lib/generators/hyrax/templates/config/initializers/hyrax.rb +1 -1
  121. data/lib/generators/hyrax/templates/config/initializers/riiif.rb +15 -5
  122. data/lib/hyrax/active_fedora_dummy_model.rb +6 -1
  123. data/lib/hyrax/configuration.rb +6 -0
  124. data/lib/hyrax/engine.rb +2 -0
  125. data/lib/hyrax/publisher.rb +19 -3
  126. data/lib/hyrax/specs/capybara.rb +9 -4
  127. data/lib/hyrax/transactions/container.rb +5 -0
  128. data/lib/hyrax/transactions/steps/add_file_sets.rb +6 -0
  129. data/lib/hyrax/transactions/steps/apply_permission_template.rb +40 -0
  130. data/lib/hyrax/transactions/steps/save.rb +21 -0
  131. data/lib/hyrax/transactions/work_create.rb +1 -0
  132. data/lib/hyrax/version.rb +1 -1
  133. data/lib/hyrax.rb +1 -0
  134. data/lib/wings/active_fedora_converter/default_work.rb +7 -2
  135. data/lib/wings/active_fedora_converter/file_metadata_node.rb +1 -1
  136. data/lib/wings/active_fedora_converter.rb +47 -11
  137. data/lib/wings/model_transformer.rb +23 -4
  138. data/lib/wings/setup.rb +21 -1
  139. data/lib/wings/valkyrie/persister.rb +4 -2
  140. data/package.json +3 -1
  141. data/template.rb +1 -1
  142. metadata +17 -12
  143. data/app/forms/hyrax/forms/file_manager_form.rb +0 -35
  144. data/app/services/hyrax/collections/migration_service.rb +0 -113
  145. data/app/views/hyrax/base/_form_collections_error.html.erb +0 -1
  146. data/app/views/hyrax/base/_form_in_works_error.html.erb +0 -3
  147. data/app/views/hyrax/base/_form_ordered_members_error.html.erb +0 -3
  148. data/app/views/hyrax/base/_form_visibility_error.html.erb +0 -19
@@ -17,6 +17,7 @@ module Hyrax
17
17
  # - "Enforced" means the object's visibility matches the pre-release
18
18
  # visibility of the embargo; i.e. the embargo has been applied,
19
19
  # but not released.
20
+ # - "Deactivate" means that the existing embargo will be removed
20
21
  #
21
22
  # Note that an resource may be `#under_embargo?` even if the embargo is not
22
23
  # be `#enforced?` (in this case, the application should seek to apply the
@@ -74,7 +75,7 @@ module Hyrax
74
75
  # resource.visibility # => 'open'
75
76
  # manager.enforced? => false
76
77
  #
77
- class EmbargoManager
78
+ class EmbargoManager # rubocop:disable Metrics/ClassLength
78
79
  ##
79
80
  # @!attribute [rw] resource
80
81
  # @return [Hyrax::Resource]
@@ -117,6 +118,51 @@ module Hyrax
117
118
  new(resource: resource, query_service: query_service)
118
119
  .release!
119
120
  end
121
+
122
+ # Creates or updates an existing embargo on a member to match the embargo on the parent work
123
+ # @param [Array<Valkyrie::Resource>] members
124
+ # @param [Hyrax::Work] work
125
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
126
+ def create_or_update_embargo_on_members(members, work)
127
+ # TODO: account for all members and levels, not just file sets. ref: #6131
128
+
129
+ members.each do |member|
130
+ member_embargo_needs_updating = work.embargo.updated_at > member.embargo&.updated_at if member.embargo
131
+
132
+ if member.embargo && member_embargo_needs_updating
133
+ member.embargo.embargo_release_date = work.embargo['embargo_release_date']
134
+ member.embargo.visibility_during_embargo = work.embargo['visibility_during_embargo']
135
+ member.embargo.visibility_after_embargo = work.embargo['visibility_after_embargo']
136
+ member.embargo = Hyrax.persister.save(resource: member.embargo)
137
+ else
138
+ work_embargo_manager = Hyrax::EmbargoManager.new(resource: work)
139
+ work_embargo_manager.copy_embargo_to(target: member)
140
+ member = Hyrax.persister.save(resource: member)
141
+ end
142
+
143
+ user ||= ::User.find_by_user_key(member.depositor)
144
+ # the line below works in that it indexes the file set with the necessary lease properties
145
+ # I do not know however if this is the best event_id to pass
146
+ Hyrax.publisher.publish('object.metadata.updated', object: member, user: user)
147
+ end
148
+ end
149
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
150
+ end
151
+
152
+ # Deactivates the embargo and logs a message to the embargo_history property
153
+ def deactivate!
154
+ embargo_state = embargo.active? ? 'active' : 'expired'
155
+ embargo_record = embargo_history_message(
156
+ embargo_state,
157
+ Time.zone.today,
158
+ embargo.embargo_release_date,
159
+ embargo.visibility_during_embargo,
160
+ embargo.visibility_after_embargo
161
+ )
162
+
163
+ release(force: true)
164
+ nullify(force: true)
165
+ embargo.embargo_history += [embargo_record]
120
166
  end
121
167
 
122
168
  ##
@@ -128,7 +174,7 @@ module Hyrax
128
174
  def copy_embargo_to(target:)
129
175
  return false unless under_embargo?
130
176
 
131
- target.embargo = Embargo.new(clone_attributes)
177
+ target.embargo = Hyrax.persister.save(resource: Embargo.new(clone_attributes))
132
178
  self.class.apply_embargo_for(resource: target)
133
179
  end
134
180
 
@@ -152,7 +198,8 @@ module Hyrax
152
198
  ##
153
199
  # @return [Boolean]
154
200
  def enforced?
155
- embargo.visibility_during_embargo.to_s == resource.visibility
201
+ embargo.embargo_release_date.present? &&
202
+ (embargo.visibility_during_embargo.to_s == resource.visibility)
156
203
  end
157
204
 
158
205
  ##
@@ -162,21 +209,28 @@ module Hyrax
162
209
  end
163
210
 
164
211
  ##
165
- # Drop the embargo by setting its release date to `nil`.
212
+ # Drop the embargo by setting its release date and visibility settings to `nil`.
213
+ #
214
+ # @param force [boolean] force the nullify even when the embargo period is current
166
215
  #
167
216
  # @return [void]
168
- def nullify
169
- return unless under_embargo?
217
+ def nullify(force: false)
218
+ return false if !force && under_embargo?
219
+
170
220
  embargo.embargo_release_date = nil
221
+ embargo.visibility_during_embargo = nil
222
+ embargo.visibility_after_embargo = nil
171
223
  end
172
224
 
173
225
  ##
174
- # Sets the visibility of the resource to the embargo's visibility condition.
175
- # no-op if the embargo period is current.
226
+ # Sets the visibility of the resource to the embargo's after embargo visibility.
227
+ # no-op if the embargo period is current and the force flag is false.
228
+ #
229
+ # @param force [boolean] force the release even when the embargo period is current
176
230
  #
177
231
  # @return [Boolean] truthy if the embargo has been applied
178
- def release
179
- return false if under_embargo?
232
+ def release(force: false)
233
+ return false if !force && under_embargo?
180
234
  return true if embargo.visibility_after_embargo.nil?
181
235
 
182
236
  resource.visibility = embargo.visibility_after_embargo
@@ -209,5 +263,17 @@ module Hyrax
209
263
  def core_attribute_keys
210
264
  [:visibility_after_embargo, :visibility_during_embargo, :embargo_release_date]
211
265
  end
266
+
267
+ protected
268
+
269
+ # Create the log message used when deactivating an embargo
270
+ def embargo_history_message(state, deactivate_date, release_date, visibility_during, visibility_after)
271
+ I18n.t 'hydra.embargo.history_message',
272
+ state: state,
273
+ deactivate_date: deactivate_date,
274
+ release_date: release_date,
275
+ visibility_during: visibility_during,
276
+ visibility_after: visibility_after
277
+ end
212
278
  end
213
279
  end
@@ -75,7 +75,7 @@ module Hyrax
75
75
  url: derivative_url('thumbnail'),
76
76
  layer: 0
77
77
  }])
78
- extract_full_text(filename, uri)
78
+ extract_full_text(filename, derivative_url('extracted_text'))
79
79
  end
80
80
 
81
81
  def create_office_document_derivatives(filename)
@@ -86,7 +86,7 @@ module Hyrax
86
86
  url: derivative_url('thumbnail'),
87
87
  layer: 0
88
88
  }])
89
- extract_full_text(filename, uri)
89
+ extract_full_text(filename, derivative_url('extracted_text'))
90
90
  end
91
91
 
92
92
  def create_audio_derivatives(filename)
@@ -122,6 +122,7 @@ module Hyrax
122
122
  # @param [String] uri to the file set (deligated to file_set)
123
123
  def extract_full_text(filename, uri)
124
124
  return unless Hyrax.config.extract_full_text?
125
+
125
126
  Hydra::Derivatives::FullTextExtract.create(filename,
126
127
  outputs: [{ url: uri, container: "extracted_text" }])
127
128
  end
@@ -4,7 +4,22 @@ module Hyrax
4
4
  ##
5
5
  # Provides utilities for managing the lifecycle of an `Hyrax::Lease` on a
6
6
  # `Hyrax::Resource`.
7
- class LeaseManager
7
+ #
8
+ # The lease terminology used here is as follows:
9
+ #
10
+ # - "Expiration Date" is the day a lease is scheduled to expire.
11
+ # - "Under Lease" means the lease is "active"; i.e. that its expiration
12
+ # date is today or later.
13
+ # - "Applied" means the lease's pre-expiration visibility has been set on
14
+ # the resource.
15
+ # - "Released" means the lease's post-expiration visibility has been set on
16
+ # the resource.
17
+ # - "Enforced" means the object's visibility matches the pre-expiration
18
+ # visibility of the lease; i.e. the lease has been applied,
19
+ # but not released.
20
+ # - "Deactivate" means that the existing lease will be removed
21
+ #
22
+ class LeaseManager # rubocop:disable Metrics/ClassLength
8
23
  ##
9
24
  # @!attribute [rw] resource
10
25
  # @return [Hyrax::Resource]
@@ -47,6 +62,51 @@ module Hyrax
47
62
  new(resource: resource, query_service: query_service)
48
63
  .release!
49
64
  end
65
+
66
+ # Creates or updates an existing lease on a member to match the lease on the parent work
67
+ # @param [Array<Valkyrie::Resource>] members
68
+ # @param [Hyrax::Work] work
69
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
70
+ def create_or_update_lease_on_members(members, work)
71
+ # TODO: account for all members and levels, not just file sets. ref: #6131
72
+
73
+ members.each do |member|
74
+ member_lease_needs_updating = work.lease.updated_at > member.lease&.updated_at if member.lease
75
+
76
+ if member.lease && member_lease_needs_updating
77
+ member.lease.lease_expiration_date = work.lease['lease_expiration_date']
78
+ member.lease.visibility_during_lease = work.lease['visibility_during_lease']
79
+ member.lease.visibility_after_lease = work.lease['visibility_after_lease']
80
+ member.lease = Hyrax.persister.save(resource: member.lease)
81
+ else
82
+ work_lease_manager = Hyrax::LeaseManager.new(resource: work)
83
+ work_lease_manager.copy_lease_to(target: member)
84
+ member = Hyrax.persister.save(resource: member)
85
+ end
86
+
87
+ user ||= ::User.find_by_user_key(member.depositor)
88
+ # the line below works in that it indexes the file set with the necessary lease properties
89
+ # I do not know however if this is the best event_id to pass
90
+ Hyrax.publisher.publish('object.metadata.updated', object: member, user: user)
91
+ end
92
+ end
93
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
94
+ end
95
+
96
+ # Deactivates the lease and logs a message to the lease_history property
97
+ def deactivate!
98
+ lease_state = lease.active? ? 'active' : 'expired'
99
+ lease_record = lease_history_message(
100
+ lease_state,
101
+ Time.zone.today,
102
+ lease.lease_expiration_date,
103
+ lease.visibility_during_lease,
104
+ lease.visibility_after_lease
105
+ )
106
+
107
+ release(force: true)
108
+ nullify(force: true)
109
+ lease.lease_history += [lease_record]
50
110
  end
51
111
 
52
112
  ##
@@ -58,7 +118,7 @@ module Hyrax
58
118
  def copy_lease_to(target:)
59
119
  return false unless under_lease?
60
120
 
61
- target.lease = Lease.new(clone_attributes)
121
+ target.lease = Hyrax.persister.save(resource: Lease.new(clone_attributes))
62
122
  self.class.apply_lease_for(resource: target)
63
123
  end
64
124
 
@@ -80,7 +140,8 @@ module Hyrax
80
140
  ##
81
141
  # @return [Boolean]
82
142
  def enforced?
83
- lease.visibility_during_lease.to_s == resource.visibility
143
+ lease.lease_expiration_date.present? &&
144
+ lease.visibility_during_lease.to_s == resource.visibility
84
145
  end
85
146
 
86
147
  ##
@@ -90,18 +151,27 @@ module Hyrax
90
151
  end
91
152
 
92
153
  ##
93
- # Drop the lease by setting its release date to `nil`.
154
+ # Drop the lease by setting its release date and visibility settings to `nil`.
94
155
  #
156
+ # @param force [boolean] force the nullify even when the lease period is current
95
157
  # @return [void]
96
- def nullify
97
- return unless under_lease?
158
+ def nullify(force: false)
159
+ return false if !force && under_lease?
160
+
98
161
  lease.lease_expiration_date = nil
162
+ lease.visibility_during_lease = nil
163
+ lease.visibility_after_lease = nil
99
164
  end
100
165
 
101
166
  ##
167
+ # Sets the visibility of the resource to the lease's after lease visibility.
168
+ # no-op if the lease period is current and the force flag is false.
169
+ #
170
+ # @param force [boolean] force the release even when the lease period is current
171
+ #
102
172
  # @return [Boolean]
103
- def release
104
- return false if under_lease?
173
+ def release(force: false)
174
+ return false if !force && under_lease?
105
175
  return true if lease.visibility_after_lease.nil?
106
176
 
107
177
  resource.visibility = lease.visibility_after_lease
@@ -131,5 +201,15 @@ module Hyrax
131
201
  def core_attribute_keys
132
202
  [:visibility_after_lease, :visibility_during_lease, :lease_expiration_date]
133
203
  end
204
+
205
+ # Create the log message used when deactivating a lease
206
+ def lease_history_message(state, deactivate_date, expiration_date, visibility_during, visibility_after)
207
+ I18n.t 'hydra.lease.history_message',
208
+ state: state,
209
+ deactivate_date: deactivate_date,
210
+ expiration_date: expiration_date,
211
+ visibility_during: visibility_during,
212
+ visibility_after: visibility_after
213
+ end
134
214
  end
135
215
  end
@@ -35,10 +35,10 @@ module Hyrax
35
35
  end
36
36
 
37
37
  ##
38
- # Called when 'object.file.uploaded' event is published
38
+ # Called when 'file.uploaded' event is published
39
39
  # @param [Dry::Events::Event] event
40
40
  # @return [void]
41
- def on_object_file_uploaded(event)
41
+ def on_file_uploaded(event)
42
42
  # Run characterization
43
43
  Hyrax.config
44
44
  .characterization_service
@@ -7,17 +7,14 @@ module Hyrax
7
7
  # manages workflow accordingly.
8
8
  class WorkflowListener
9
9
  ##
10
- # @note respects class attribute configuration at
11
- # {Hyrax::Actors::InitializeWorkflowActor.workflow_factory}, but falls
12
- # back on {Hyrax::Workflow::WorkflowFactory} to prepare for removal of
13
- # Actors
14
- # @return [#create] default: {Hyrax::Workflow::WorkflowFactory}
15
- def factory
16
- if defined?(Hyrax::Actors::InitializeWorkflowActor)
17
- Hyrax::Actors::InitializeWorkflowActor.workflow_factory
18
- else
19
- Hyrax::Workflow::WorkflowFactory
20
- end
10
+ # @!attribute [rw] factory
11
+ # @return [#create]
12
+ attr_accessor :factory
13
+
14
+ ##
15
+ # @param [#create] factory
16
+ def initialize(factory: Hyrax::Workflow::WorkflowFactory)
17
+ @factory = factory
21
18
  end
22
19
 
23
20
  ##
@@ -24,11 +24,33 @@ module Hyrax
24
24
  # @option directives [String] url URI for the parent object.
25
25
  def self.retrieve_file_set(directives)
26
26
  uri = URI(directives.fetch(:url))
27
- raise ArgumentError, "#{uri} is not an http(s) uri" unless uri.is_a?(URI::HTTP)
28
- Hyrax.query_service.find_by_alternate_identifier(alternate_identifier: Hyrax::Base.uri_to_id(uri.to_s), use_valkyrie: false)
27
+ if uri.is_a?(URI::HTTP)
28
+ Hyrax.query_service.find_by_alternate_identifier(alternate_identifier: Hyrax::Base.uri_to_id(uri.to_s), use_valkyrie: false)
29
+ else
30
+ raise ArgumentError, "#{uri} is not an file/http(s) uri" unless uri.is_a?(URI::File)
31
+
32
+ fileset_for_directives(directives)
33
+ end
29
34
  end
30
35
  private_class_method :retrieve_file_set
31
36
 
37
+ # The filepath will look something like
38
+ # /app/samvera/hyrax-webapp/derivatives/95/93/tv/12/3-thumbnail.jpeg and
39
+ # we want to extract the FileSet id, which in this case would be 9593tv123
40
+ #
41
+ # @param [String] path
42
+ # @return [Hyrax::FileSet]
43
+ def self.fileset_for_directives(directives)
44
+ path = URI(directives.fetch(:url)).path
45
+ id = path.sub(Hyrax.config.derivatives_path.to_s, "")
46
+ .delete('/')
47
+ .match(/^(.*)-\w*(\.\w+)*$/) { |m| m[1] }
48
+ raise "Could not extract fileset id from path #{path}" unless id
49
+
50
+ Hyrax.metadata_adapter.query_service.find_by(id: id)
51
+ end
52
+ private_class_method :fileset_for_directives
53
+
32
54
  # Override this implementation if you need a remote file from a different location
33
55
  # @param file_set [FileSet] the container of the remote file
34
56
  # @param directives [Hash] directions which can be used to determine where to persist to
@@ -28,21 +28,21 @@ module Hyrax
28
28
  ##
29
29
  # execute the query using a GET request
30
30
  # @return [Hash] the results returned from solr for the current query
31
- def get
32
- solr_service.get(build)
31
+ def get(**args)
32
+ solr_service.get(build, **args)
33
33
  end
34
34
 
35
35
  ##
36
36
  # execute the solr query and return results
37
37
  # @return [Hash] the results returned from solr for the current query
38
- def query_result
39
- solr_service.query_result(build)
38
+ def query_result(**args)
39
+ solr_service.query_result(build, **args)
40
40
  end
41
41
 
42
42
  ##
43
43
  # @return [Enumerable<SolrDocument>]
44
- def solr_documents
45
- query_result['response']['docs'].map { |doc| self.class.document_model.new(doc) }
44
+ def solr_documents(**args)
45
+ query_result(**args)['response']['docs'].map { |doc| self.class.document_model.new(doc) }
46
46
  end
47
47
 
48
48
  ##
@@ -107,6 +107,7 @@ module Hyrax
107
107
  def with_generic_type(generic_type: 'Work')
108
108
  # TODO: Generic type was originally stored as `sim`. Since it is never multi-valued, it is moving to being stored
109
109
  # as `si`. Until a migration is created to correct existing solr docs, this query searches in both fields.
110
+ # @see https://github.com/samvera/hyrax/issues/6086
110
111
  field_pairs = { generic_type_si: generic_type, generic_type_sim: generic_type }
111
112
  type_query = construct_query_for_pairs(field_pairs, ' OR ', 'field')
112
113
  @query += [type_query]
@@ -58,7 +58,7 @@ module Hyrax
58
58
  end
59
59
 
60
60
  def query_service
61
- Hyrax::Statistics::QueryService.new
61
+ Hyrax::Statistics::ValkyrieQueryService.new
62
62
  end
63
63
  end
64
64
  end
@@ -40,7 +40,7 @@ module Hyrax
40
40
  end
41
41
 
42
42
  def query_service
43
- Hyrax::Statistics::QueryService.new
43
+ Hyrax::Statistics::ValkyrieQueryService.new
44
44
  end
45
45
 
46
46
  # How many points are in this data set
@@ -26,7 +26,9 @@ module Hyrax
26
26
  end
27
27
 
28
28
  def point(date_string)
29
- relation.where(query(date_string)).count
29
+ # convert the User::ActiveRecord_Relation to an array so that ".size" returns a number,
30
+ # instead of a hash of { user_id: size }
31
+ relation.where(query(date_string)).to_a.size
30
32
  end
31
33
  end
32
34
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module Statistics
4
+ class ValkyrieQueryService < QueryService
5
+ # query to find works created during the time range
6
+ # @param [DateTime] start_datetime starting date time for range query
7
+ # @param [DateTime] end_datetime ending date time for range query
8
+ def find_by_date_created(start_datetime, end_datetime = nil)
9
+ return [] if start_datetime.blank? # no date just return nothing
10
+ return super unless non_wings_valkyire?
11
+
12
+ Hyrax.query_service.custom_queries.find_by_date_range(start_datetime: start_datetime,
13
+ end_datetime: end_datetime,
14
+ models: relation.allowable_types).to_a
15
+ end
16
+
17
+ def find_registered_in_date_range(start_datetime, end_datetime = nil)
18
+ return super unless non_wings_valkyire?
19
+ find_by_date_created(start_datetime, end_datetime) & where_registered.to_a
20
+ end
21
+
22
+ def find_public_in_date_range(start_datetime, end_datetime = nil)
23
+ return super unless non_wings_valkyire?
24
+ find_by_date_created(start_datetime, end_datetime) & where_public.to_a
25
+ end
26
+
27
+ def relation
28
+ return super unless non_wings_valkyire?
29
+ Hyrax::ValkyrieWorkRelation.new
30
+ end
31
+
32
+ private
33
+
34
+ def where_access_is(access_level)
35
+ # returns all works where the access level is public
36
+ return super unless non_wings_valkyire?
37
+
38
+ Hyrax.custom_queries.find_models_by_access(mode: 'read',
39
+ models: relation.allowable_types,
40
+ group: true,
41
+ agent: access_level)
42
+ end
43
+
44
+ def non_wings_valkyire?
45
+ Hyrax.config.use_valkyrie? && (!defined?(Wings) || (defined?(Wings) && Hyrax.config.disable_wings))
46
+ end
47
+ end
48
+ end
49
+ end
@@ -44,7 +44,7 @@ module Hyrax
44
44
  private
45
45
 
46
46
  def query_service
47
- @query_service ||= Hyrax::Statistics::QueryService.new
47
+ @query_service ||= Hyrax::Statistics::ValkyrieQueryService.new
48
48
  end
49
49
 
50
50
  def by_date_and_permission
@@ -30,6 +30,11 @@ module Hyrax
30
30
  def fetch_thumbnail(object)
31
31
  return object if object.thumbnail_id == object.id ||
32
32
  object.try(:file_ids)&.detect { |fid| fid == object.thumbnail_id }
33
+ begin
34
+ return Hyrax.query_service.find_by(id: object.thumbnail_id)
35
+ rescue
36
+ nil
37
+ end
33
38
  Hyrax.query_service.find_by_alternate_identifier(alternate_identifier: object.thumbnail_id)
34
39
  rescue Valkyrie::Persistence::ObjectNotFoundError, Hyrax::ObjectNotFoundError
35
40
  Hyrax.logger.error("Couldn't find thumbnail #{object.thumbnail_id} for #{object.id}")
@@ -22,20 +22,17 @@ module Hyrax
22
22
  file_set = fileset_for_directives(directives)
23
23
 
24
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
25
+ # responds to #rewind and #read so we have created a StringIO
27
26
  tmpfile = Tempfile.new(file_set.id, encoding: 'ascii-8bit')
28
- tmpfile.write stream.read
27
+ stream = StringIO.new(stream) if stream.is_a?(String)
28
+ stream.rewind
29
+ output = tmpfile.write(stream.read)
30
+ tmpfile.flush
31
+ raise 'blank file detected' if output.zero?
29
32
 
30
33
  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
38
- )
34
+ Hyrax.logger.debug "Uploading derivative for FileSet #{file_set.id} as #{filename}"
35
+ uploader.upload(io: tmpfile, filename: filename, file_set: file_set, use: file_metadata(directives))
39
36
  end
40
37
 
41
38
  # The filepath will look something like
@@ -57,5 +54,13 @@ module Hyrax
57
54
  def self.filename(directives)
58
55
  URI(directives.fetch(:url)).path.split('/').last
59
56
  end
57
+
58
+ def self.file_metadata(directives)
59
+ if directives.key?(:container)
60
+ "Hyrax::FileMetadata::Use::#{directives[:container].upcase}".constantize
61
+ else
62
+ Hyrax::FileMetadata::Use::THUMBNAIL
63
+ end
64
+ end
60
65
  end
61
66
  end
@@ -38,7 +38,8 @@ class Hyrax::ValkyrieUpload
38
38
  streamfile = storage_adapter.upload(file: io, original_filename: filename, resource: file_set)
39
39
  file_metadata = Hyrax::FileMetadata(streamfile)
40
40
  file_metadata.file_set_id = file_set.id
41
- file_metadata.type += [use]
41
+ file_metadata.pcdm_use = [use]
42
+ file_metadata.recorded_size = [io.size]
42
43
 
43
44
  if use == Hyrax::FileMetadata::Use::ORIGINAL_FILE
44
45
  # Set file set label.
@@ -50,7 +51,8 @@ class Hyrax::ValkyrieUpload
50
51
  end
51
52
 
52
53
  saved_metadata = Hyrax.persister.save(resource: file_metadata)
53
- Hyrax.publisher.publish("object.file.uploaded", metadata: saved_metadata)
54
+ saved_metadata.original_filename = filename if saved_metadata.original_filename.blank?
55
+ Hyrax.publisher.publish("file.uploaded", metadata: saved_metadata)
54
56
 
55
57
  add_file_to_file_set(file_set: file_set,
56
58
  file_metadata: saved_metadata,
@@ -83,7 +85,7 @@ class Hyrax::ValkyrieUpload
83
85
  # the file to add
84
86
  # @return [void]
85
87
  def set_file_use_ids(file_set, file_metadata)
86
- file_metadata.type.each do |type|
88
+ file_metadata.pcdm_use.each do |type|
87
89
  case type
88
90
  when Hyrax::FileMetadata::Use::ORIGINAL_FILE
89
91
  file_set.original_file_id = file_metadata.id
@@ -41,6 +41,7 @@ module Hyrax
41
41
  []
42
42
  end
43
43
  else
44
+ return resource.versions if resource.versions.is_a?(Array)
44
45
  resource.versions.all.to_a
45
46
  end
46
47
  end
@@ -86,10 +86,7 @@ module Hyrax
86
86
  return true if date.is_a?(Date)
87
87
  return true if date.is_a?(Time)
88
88
  Date.parse(date)
89
- # In Ruby 2.7.x, Date::Error descends from ArgumentError; Once
90
- # we stop supporting pre-2.7, we can switch this to the more
91
- # narrow Date::Error
92
- rescue ArgumentError
89
+ rescue Date::Error
93
90
  false
94
91
  end
95
92
  end
@@ -10,7 +10,7 @@ module Hyrax
10
10
  # @return [#propagate]
11
11
  def self.for(source:)
12
12
  case source
13
- when Hyrax::WorkBehavior # ActiveFedora
13
+ when ActiveFedora::Base # ActiveFedora
14
14
  FileSetVisibilityPropagator.new(source: source)
15
15
  when Hyrax::Resource # Valkyrie
16
16
  ResourceVisibilityPropagator.new(source: source)