hyrax 3.3.0 → 3.4.0

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/.dassie/config/initializers/hyrax.rb +11 -1
  3. data/.gitignore +3 -0
  4. data/.regen +1 -1
  5. data/.rubocop_fixme.yml +3 -1
  6. data/Dockerfile +2 -1
  7. data/app/actors/hyrax/actors/file_actor.rb +6 -4
  8. data/app/actors/hyrax/actors/transfer_request_actor.rb +3 -7
  9. data/app/assets/javascripts/hyrax/analytics_events.js +8 -2
  10. data/app/assets/javascripts/hyrax/autocomplete/linked_data.es6 +1 -3
  11. data/app/controllers/concerns/hyrax/controller.rb +21 -0
  12. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +83 -59
  13. data/app/controllers/hyrax/admin/admin_sets_controller.rb +105 -19
  14. data/app/controllers/hyrax/admin/permission_template_accesses_controller.rb +12 -19
  15. data/app/controllers/hyrax/batch_edits_controller.rb +12 -3
  16. data/app/controllers/hyrax/batch_uploads_controller.rb +4 -0
  17. data/app/controllers/hyrax/citations_controller.rb +1 -1
  18. data/app/controllers/hyrax/dashboard/collections_controller.rb +19 -10
  19. data/app/forms/hyrax/forms/administrative_set_form.rb +19 -1
  20. data/app/forms/hyrax/forms/batch_edit_form.rb +1 -1
  21. data/app/forms/hyrax/forms/dashboard/nest_collection_form.rb +21 -6
  22. data/app/forms/hyrax/forms/pcdm_collection_form.rb +1 -0
  23. data/app/forms/hyrax/forms/permission_template_form.rb +17 -9
  24. data/app/forms/hyrax/forms/resource_form.rb +9 -5
  25. data/app/helpers/hyrax/collections_helper.rb +14 -0
  26. data/app/helpers/hyrax/membership_helper.rb +1 -1
  27. data/app/helpers/hyrax/trophy_helper.rb +1 -1
  28. data/app/helpers/hyrax/url_helper.rb +1 -1
  29. data/app/indexers/hyrax/administrative_set_indexer.rb +8 -2
  30. data/app/indexers/hyrax/deep_indexing_service.rb +1 -1
  31. data/app/indexers/hyrax/file_set_indexer.rb +1 -0
  32. data/app/indexers/hyrax/pcdm_collection_indexer.rb +3 -1
  33. data/app/indexers/hyrax/thumbnail_indexer.rb +31 -0
  34. data/app/indexers/hyrax/valkyrie_file_set_indexer.rb +6 -6
  35. data/app/indexers/hyrax/valkyrie_indexer.rb +4 -2
  36. data/app/indexers/hyrax/valkyrie_work_indexer.rb +13 -0
  37. data/app/inputs/controlled_vocabulary_input.rb +2 -0
  38. data/app/jobs/change_depositor_event_job.rb +47 -0
  39. data/app/jobs/characterize_job.rb +38 -2
  40. data/app/jobs/concerns/hyrax/members_permission_job_behavior.rb +1 -1
  41. data/app/jobs/content_depositor_change_event_job.rb +2 -1
  42. data/app/jobs/hyrax/propagate_change_depositor_job.rb +32 -0
  43. data/app/jobs/inherit_permissions_job.rb +1 -1
  44. data/app/jobs/valkyrie_create_derivatives_job.rb +25 -0
  45. data/app/jobs/valkyrie_ingest_job.rb +84 -16
  46. data/app/models/admin_set.rb +2 -2
  47. data/app/models/collection_branding_info.rb +8 -6
  48. data/app/models/concerns/hyrax/collection_behavior.rb +2 -2
  49. data/app/models/concerns/hyrax/file_set/characterization.rb +7 -1
  50. data/app/models/concerns/hyrax/solr_document/metadata.rb +1 -0
  51. data/app/models/concerns/hyrax/solr_document_behavior.rb +9 -3
  52. data/app/models/hyrax/administrative_set.rb +36 -1
  53. data/app/models/hyrax/collection_type.rb +2 -2
  54. data/app/models/hyrax/file_metadata.rb +5 -1
  55. data/app/models/hyrax/file_set.rb +42 -1
  56. data/app/models/hyrax/pcdm_collection.rb +56 -0
  57. data/app/models/hyrax/permission_template.rb +11 -5
  58. data/app/models/hyrax/work.rb +91 -0
  59. data/app/models/proxy_deposit_request.rb +1 -1
  60. data/app/presenters/hyrax/admin_set_presenter.rb +2 -2
  61. data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +2 -2
  62. data/app/presenters/hyrax/work_show_presenter.rb +7 -3
  63. data/app/search_builders/hyrax/dashboard/collections_search_builder.rb +2 -2
  64. data/app/search_builders/hyrax/dashboard/managed_search_filters.rb +44 -4
  65. data/app/search_builders/hyrax/dashboard/nested_collections_search_builder.rb +2 -2
  66. data/app/search_builders/hyrax/my/collections_search_builder.rb +11 -4
  67. data/app/services/hyrax/access_control_list.rb +13 -0
  68. data/app/services/hyrax/admin_set_create_service.rb +21 -37
  69. data/app/services/hyrax/change_content_depositor_service.rb +2 -2
  70. data/app/services/hyrax/change_depositor_service.rb +70 -0
  71. data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +1 -1
  72. data/app/services/hyrax/collections/nested_collection_query_service.rb +23 -11
  73. data/app/services/hyrax/custom_queries/navigators/child_file_sets_navigator.rb +45 -0
  74. data/app/services/hyrax/custom_queries/navigators/child_filesets_navigator.rb +7 -2
  75. data/app/services/hyrax/custom_queries/navigators/parent_work_navigator.rb +54 -0
  76. data/app/services/hyrax/default_middleware_stack.rb +3 -0
  77. data/app/services/hyrax/file_set_derivatives_service.rb +21 -2
  78. data/app/services/hyrax/file_set_type_service.rb +2 -5
  79. data/app/services/hyrax/listeners/file_metadata_listener.rb +20 -1
  80. data/app/services/hyrax/listeners/member_cleanup_listener.rb +23 -3
  81. data/app/services/hyrax/listeners/metadata_index_listener.rb +39 -0
  82. data/app/services/hyrax/listeners/proxy_deposit_listener.rb +14 -8
  83. data/app/services/hyrax/location_service.rb +33 -0
  84. data/app/services/hyrax/multiple_membership_checker.rb +44 -1
  85. data/app/services/hyrax/resource_visibility_propagator.rb +1 -1
  86. data/app/services/hyrax/simple_schema_loader.rb +5 -1
  87. data/app/services/hyrax/solr_query_service.rb +12 -7
  88. data/app/services/hyrax/thumbnail_path_service.rb +1 -1
  89. data/app/services/hyrax/work_uploads_handler.rb +0 -10
  90. data/app/validators/hyrax/collection_membership_validator.rb +38 -0
  91. data/app/views/catalog/_index_header_list_hyrax_pcdm_collection.html.erb +4 -0
  92. data/app/views/hyrax/admin/admin_sets/_form_participant_table.html.erb +2 -2
  93. data/app/views/hyrax/admin/admin_sets/_form_participants.html.erb +2 -2
  94. data/app/views/hyrax/admin/admin_sets/_form_visibility.html.erb +2 -2
  95. data/app/views/hyrax/admin/admin_sets/_form_workflow.erb +1 -1
  96. data/app/views/hyrax/admin/collection_types/index.html.erb +1 -1
  97. data/app/views/hyrax/base/_form.html.erb +1 -1
  98. data/app/views/hyrax/base/_form_child_work_relationships.html.erb +1 -1
  99. data/app/views/hyrax/dashboard/collections/_default_group.html.erb +2 -2
  100. data/app/views/hyrax/dashboard/collections/_form.html.erb +21 -15
  101. data/app/views/hyrax/dashboard/collections/_form_discovery.html.erb +6 -3
  102. data/app/views/hyrax/dashboard/collections/_form_share.html.erb +2 -2
  103. data/app/views/hyrax/dashboard/collections/_form_share_table.html.erb +3 -3
  104. data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +2 -2
  105. data/app/views/hyrax/dashboard/works/_default_group.html.erb +1 -1
  106. data/app/views/hyrax/dashboard/works/_list_works.html.erb +1 -1
  107. data/app/views/hyrax/file_sets/_actions.html.erb +2 -2
  108. data/app/views/hyrax/my/_work_action_menu.html.erb +8 -9
  109. data/app/views/hyrax/my/collections/_default_group.html.erb +2 -2
  110. data/app/views/hyrax/my/collections/_list_collections.html.erb +2 -2
  111. data/app/views/hyrax/my/collections/index.html.erb +3 -2
  112. data/app/views/hyrax/my/works/_default_group.html.erb +1 -1
  113. data/app/views/hyrax/my/works/_list_works.html.erb +1 -2
  114. data/app/views/hyrax/my/works/index.html.erb +4 -2
  115. data/chart/hyrax/Chart.yaml +2 -2
  116. data/chart/hyrax/README.md +22 -1
  117. data/config/initializers/listeners.rb +0 -1
  118. data/config/locales/hyrax.de.yml +6 -5
  119. data/config/locales/hyrax.en.yml +30 -28
  120. data/config/locales/hyrax.es.yml +10 -9
  121. data/config/locales/hyrax.fr.yml +2 -1
  122. data/config/locales/hyrax.it.yml +3 -2
  123. data/config/locales/hyrax.pt-BR.yml +2 -1
  124. data/config/locales/hyrax.zh.yml +2 -1
  125. data/config/metadata/basic_metadata.yaml +2 -0
  126. data/config/metadata/core_metadata.yaml +1 -1
  127. data/docker-compose.yml +46 -42
  128. data/documentation/developing-your-hyrax-based-app.md +1 -1
  129. data/documentation/legacyREADME.md +1 -1
  130. data/lib/hyrax/administrative_set_name.rb +18 -0
  131. data/lib/hyrax/collection_name.rb +2 -0
  132. data/lib/hyrax/configuration.rb +10 -0
  133. data/lib/hyrax/controlled_vocabularies/location.rb +9 -2
  134. data/lib/hyrax/controlled_vocabularies/resource_label_caching.rb +42 -0
  135. data/lib/hyrax/controlled_vocabularies.rb +1 -0
  136. data/lib/hyrax/publisher.rb +45 -0
  137. data/lib/hyrax/specs/capybara.rb +1 -1
  138. data/lib/hyrax/specs/shared_specs/hydra_works.rb +11 -4
  139. data/lib/hyrax/specs/shared_specs/indexers.rb +117 -3
  140. data/lib/hyrax/transactions/admin_set_create.rb +2 -1
  141. data/lib/hyrax/transactions/admin_set_destroy.rb +22 -0
  142. data/lib/hyrax/transactions/admin_set_update.rb +21 -0
  143. data/lib/hyrax/transactions/collection_destroy.rb +22 -0
  144. data/lib/hyrax/transactions/collection_update.rb +3 -2
  145. data/lib/hyrax/transactions/container.rb +87 -23
  146. data/lib/hyrax/transactions/create_work.rb +3 -0
  147. data/lib/hyrax/transactions/destroy_work.rb +3 -0
  148. data/lib/hyrax/transactions/steps/apply_collection_permission_template.rb +2 -0
  149. data/lib/hyrax/transactions/steps/apply_permission_template.rb +2 -0
  150. data/lib/hyrax/transactions/steps/apply_visibility.rb +2 -0
  151. data/lib/hyrax/transactions/steps/change_depositor.rb +46 -0
  152. data/lib/hyrax/transactions/steps/check_for_empty_admin_set.rb +36 -0
  153. data/lib/hyrax/transactions/steps/delete_access_control.rb +32 -0
  154. data/lib/hyrax/transactions/steps/delete_resource.rb +19 -3
  155. data/lib/hyrax/transactions/steps/destroy_work.rb +3 -1
  156. data/lib/hyrax/transactions/steps/ensure_permission_template.rb +2 -0
  157. data/lib/hyrax/transactions/steps/save.rb +24 -6
  158. data/lib/hyrax/transactions/steps/save_access_control.rb +2 -2
  159. data/lib/hyrax/transactions/steps/save_work.rb +3 -0
  160. data/lib/hyrax/transactions/steps/set_user_as_creator.rb +41 -0
  161. data/lib/hyrax/transactions/steps/update_work_members.rb +51 -0
  162. data/lib/hyrax/transactions/update_work.rb +4 -3
  163. data/lib/hyrax/transactions/work_create.rb +1 -1
  164. data/lib/hyrax/transactions/work_destroy.rb +2 -1
  165. data/lib/hyrax/transactions/work_update.rb +19 -0
  166. data/lib/hyrax/version.rb +1 -1
  167. data/lib/wings/attribute_transformer.rb +5 -1
  168. data/lib/wings/setup.rb +3 -1
  169. data/lib/wings/valkyrie/query_service.rb +2 -1
  170. data/lib/wings/valkyrie/storage.rb +7 -1
  171. data/template.rb +1 -1
  172. metadata +24 -3
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module ControlledVocabularies
4
+ ##
5
+ # adds caching to the {#rdf_label} method.
6
+ #
7
+ # for systems that check the {#rdf_label}and use {#fetch} to get upstream
8
+ # data if it is not present, this can be used to avoid making round trips
9
+ # to an authoritative web source.
10
+ #
11
+ # @see Hyrax::DeepIndexingService
12
+ module ResourceLabelCaching
13
+ CACHE_KEY_PREFIX = "hy_label-v1-"
14
+
15
+ ##
16
+ # @note uses the Rails cache to avoid repeated lookups.
17
+ # @see ActiveTriples::Resource#rdf_label
18
+ def rdf_label
19
+ # only cache if this rdf source is represented by a URI;
20
+ # i.e. don't cache for blank nodes
21
+ return super unless uri?
22
+
23
+ Rails.cache.fetch(cache_key) { super }
24
+ end
25
+
26
+ ##
27
+ # @note adds behavior to clear the cache whenever a manual fetch of data
28
+ # is performed.
29
+ # @see ActiveTriples::Resource#fetch
30
+ def fetch(*)
31
+ Rails.cache.delete(cache_key)
32
+ super
33
+ end
34
+
35
+ private
36
+
37
+ def cache_key
38
+ "#{CACHE_KEY_PREFIX}#{to_uri.canonicalize.pname}"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -5,6 +5,7 @@ module Hyrax
5
5
 
6
6
  eager_autoload do
7
7
  autoload :Location
8
+ autoload :ResourceLabelCaching
8
9
  end
9
10
  end
10
11
  end
@@ -94,18 +94,45 @@ module Hyrax
94
94
  # @macro a_registered_event
95
95
  register_event('batch.created')
96
96
 
97
+ # @since 3.4.0
98
+ # @macro a_registered_event
99
+ register_event('collection.deleted')
100
+
97
101
  # @since 3.0.0
98
102
  # @macro a_registered_event
103
+ # @note this event SHOULD be published whevener the metadata is saved
104
+ # for a PCDM Collection. the payload for each published event MUST
105
+ # include an `:collection` (the updated Collection) AND a `:user` (the
106
+ # {::User} responsible for the update). the event SHOULD NOT be
107
+ # published for changes that only impact membership properties
108
+ # (`#member_of_ids`, `#member_of_collection_ids`, and `#member_ids`)
99
109
  register_event('collection.metadata.updated')
100
110
 
101
111
  # @since 3.0.0
102
112
  # @macro a_registered_event
113
+ # @note this event SHOULD be published whevener the membership is changed
114
+ # for a PCDM Collection. this includes changes to the Collection's
115
+ # `#member_ids` attribute, as well as inverse membership changes via
116
+ # another Collection/Object's `#member_of_ids` or
117
+ # `#member_of_collection_ids` attribute. the event payload MUST include
118
+ # either a `:collection` OR a `:collection_id` (the Collection OR its
119
+ # unique id), AND a `:user` (the ::User responsible for the update).
103
120
  register_event('collection.membership.updated')
104
121
 
105
122
  # @since 3.3.0
106
123
  # @macro a_registered_event
107
124
  register_event('file.downloaded')
108
125
 
126
+ # @since 3.4.0
127
+ # @macro a_registered_event
128
+ # @note this event SHOULD be published whenever a {Hyrax::FileMetadata}
129
+ # object is updated; i.e. whenever the metadata directly associated with
130
+ # a file changes. the event payload MUST include a `:metadata` (the
131
+ # {Hyrax::FileMetadata} that has been updated) AND a `:user`. note that
132
+ # the `:user` responsible for {FileMetadata} changes may frequently be
133
+ # a system user.
134
+ register_event('file.metadata.updated')
135
+
109
136
  # @since 3.0.0
110
137
  # @macro a_registered_event
111
138
  register_event('file.set.audited')
@@ -138,8 +165,26 @@ module Hyrax
138
165
  # @macro a_registered_event
139
166
  register_event('object.acl.updated')
140
167
 
168
+ # @since 3.4.0
169
+ # @macro a_registered_event
170
+ # @note this event SHOULD be published whevener the membership is changed
171
+ # for a PCDM Object (including a Hydra Works FileSet). this includes
172
+ # changes to the Object's `#member_ids` attribute, as well as inverse
173
+ # membership changes via another Object's `#member_of_ids` attribute.
174
+ # the event payload MUST include either an `:object` OR an `:object_id`
175
+ # (the Object OR its unique id), AND a `:user` (the ::User responsible
176
+ # for the update).
177
+ register_event('object.membership.updated')
178
+
141
179
  # @since 3.0.0
142
180
  # @macro a_registered_event
181
+ # @note this event SHOULD be published whevener the metadata is saved
182
+ # for a PCDM Object (including a Hydra Works FileSet). the payload for
183
+ # each published event MUST include an `:object` (the updated Object),
184
+ # AND a `:user` (the ::User responsible for the update). the event
185
+ # SHOULD NOT be published for changes that only impact membership
186
+ # properties (`#member_of_ids`, `#member_of_collection_ids`, and
187
+ # `#member_ids`)
143
188
  register_event('object.metadata.updated')
144
189
 
145
190
  # @since 3.2.0
@@ -21,7 +21,7 @@ if ENV['IN_DOCKER'].present? || ENV['HUB_URL'].present?
21
21
  args = %w[disable-gpu no-sandbox whitelisted-ips window-size=1400,1400]
22
22
  args.push('headless') if ActiveModel::Type::Boolean.new.cast(ENV['CHROME_HEADLESS_MODE'])
23
23
 
24
- capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(chromeOptions: { args: args })
24
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome("goog:chromeOptions" => { args: args })
25
25
 
26
26
  Capybara.register_driver :selenium_chrome_headless_sandboxless do |app|
27
27
  driver = Capybara::Selenium::Driver.new(app,
@@ -172,10 +172,12 @@ RSpec.shared_examples 'a Hyrax::AdministrativeSet' do
172
172
  .to contain_exactly('lorem ipsum')
173
173
  end
174
174
 
175
- it 'has an #title' do
176
- expect { admin_set.title = ['Moomin'] }
177
- .to change { admin_set.title }
178
- .to contain_exactly('Moomin')
175
+ describe '#collection_type_gid' do
176
+ let(:gid) { Hyrax::CollectionType.find_or_create_admin_set_type.to_global_id }
177
+
178
+ it 'has a GlobalID for a collection type' do
179
+ expect(admin_set.collection_type_gid).to eq gid
180
+ end
179
181
  end
180
182
  end
181
183
 
@@ -256,6 +258,7 @@ RSpec.shared_examples 'a Hyrax::FileSet' do
256
258
 
257
259
  it_behaves_like 'a Hyrax::Resource'
258
260
  it_behaves_like 'a model with core metadata'
261
+ it_behaves_like 'a model with basic metadata'
259
262
 
260
263
  it { is_expected.not_to be_collection }
261
264
  it { is_expected.not_to be_file }
@@ -287,6 +290,10 @@ RSpec.shared_examples 'a Hyrax::FileSet' do
287
290
  expect(fileset.file_ids).to eq file_ids
288
291
  end
289
292
 
293
+ it 'has a representative_id' do
294
+ expect(fileset.representative_id).to eq fileset.id
295
+ end
296
+
290
297
  it 'can query files' do
291
298
  expect(query_service.custom_queries.find_files(file_set: fileset)).to eq files
292
299
  end
@@ -85,6 +85,27 @@ RSpec.shared_examples 'a visibility indexer' do
85
85
  end
86
86
  end
87
87
 
88
+ RSpec.shared_examples 'a thumbnail indexer' do
89
+ before do
90
+ raise 'indexer_class must be set with `let(:indexer_class)`' unless defined? indexer_class
91
+ raise 'resource must be set with `let(:resource)` and is expected to be a kind of Hyrax::Resource' unless defined?(resource) && resource.kind_of?(Hyrax::Resource)
92
+ # optionally can pass in default_visibility by setting it with a let statement if your application changes the default; Hyrax defines this as 'restricted'
93
+ # See samvera/hyrda-head hydra-access-controls/app/models/concerns/hydra/access_controls/access_rights.rb for possible VISIBILITY_TEXT_VALUE_...'
94
+ end
95
+ subject(:indexer) { indexer_class.new(resource: resource) }
96
+ let(:thumbnail_path) { '/downloads/foo12345?file=thumbnail' }
97
+
98
+ before do
99
+ allow(indexer.thumbnail_path_service).to receive(:call).and_return(thumbnail_path)
100
+ end
101
+
102
+ describe '#to_solr' do
103
+ it 'indexes a thumbnail path' do
104
+ expect(indexer.to_solr).to include(thumbnail_path_ss: thumbnail_path)
105
+ end
106
+ end
107
+ end
108
+
88
109
  RSpec.shared_examples 'a Core metadata indexer' do
89
110
  before do
90
111
  raise 'indexer_class must be set with `let(:indexer_class)`' unless defined? indexer_class
@@ -144,6 +165,53 @@ RSpec.shared_examples 'a Basic metadata indexer' do
144
165
  end
145
166
  end
146
167
 
168
+ RSpec.shared_examples 'a File Set indexer' do
169
+ before do
170
+ raise 'indexer_class must be set with `let(:indexer_class)`' unless defined? indexer_class
171
+ # NOTE: resource must be persisted for permission tests to pass
172
+ raise 'resource must be set with `let(:resource)` and is expected to be a kind of Hyrax::FileSet' unless defined?(resource) && resource.kind_of?(Hyrax::FileSet)
173
+ # optionally can pass in default_visibility by setting it with a let statement if your application changes the default; Hyrax defines this as 'restricted'
174
+ # See samvera/hyrda-head hydra-access-controls/app/models/concerns/hydra/access_controls/access_rights.rb for possible VISIBILITY_TEXT_VALUE_...'
175
+ end
176
+ subject(:indexer) { indexer_class.new(resource: resource) }
177
+ let(:file_ids) { ['fileid1', 'fileid2'] }
178
+
179
+ it_behaves_like 'a Hyrax::Resource indexer'
180
+ it_behaves_like 'a Core metadata indexer'
181
+ it_behaves_like 'a Basic metadata indexer'
182
+ it_behaves_like 'a permission indexer'
183
+ it_behaves_like 'a visibility indexer'
184
+ it_behaves_like 'a thumbnail indexer'
185
+
186
+ describe '#to_solr' do
187
+ it 'indexes generic type' do
188
+ expect(indexer.to_solr)
189
+ .to include(generic_type_sim: a_collection_containing_exactly('FileSet'))
190
+ end
191
+
192
+ it 'indexed file ids' do
193
+ expect(indexer.to_solr)
194
+ .to include(file_ids_ssim: a_collection_containing_exactly(*ids))
195
+ end
196
+
197
+ it 'indexes representative id' do
198
+ expect(indexer.to_solr)
199
+ .to include(hasRelatedMediaFragment_ssim: a_collection_containing_exactly(an_instance_of(String)))
200
+ end
201
+
202
+ it 'indexes thumbnail id' do
203
+ expect(indexer.to_solr)
204
+ .to include(hasRelatedImage_ssim: a_collection_containing_exactly(an_instance_of(String)))
205
+ end
206
+
207
+ it 'indexes depositor' do
208
+ expect(indexer.to_solr)
209
+ .to include(depositor_ssim: [resource.depositor],
210
+ depositor_tesim: [resource.depositor])
211
+ end
212
+ end
213
+ end
214
+
147
215
  RSpec.shared_examples 'a Work indexer' do
148
216
  before do
149
217
  raise 'indexer_class must be set with `let(:indexer_class)`' unless defined? indexer_class
@@ -158,6 +226,19 @@ RSpec.shared_examples 'a Work indexer' do
158
226
  it_behaves_like 'a Core metadata indexer'
159
227
  it_behaves_like 'a permission indexer'
160
228
  it_behaves_like 'a visibility indexer'
229
+ it_behaves_like 'a thumbnail indexer'
230
+
231
+ describe '#to_solr' do
232
+ it 'indexes representative id' do
233
+ expect(indexer.to_solr)
234
+ .to include('hasRelatedMediaFragment_ssim': a_collection_containing_exactly(an_instance_of(String)))
235
+ end
236
+
237
+ it 'indexes thumbnail id' do
238
+ expect(indexer.to_solr)
239
+ .to include('hasRelatedImage_ssim': a_collection_containing_exactly(an_instance_of(String)))
240
+ end
241
+ end
161
242
  end
162
243
 
163
244
  RSpec.shared_examples 'a Collection indexer' do
@@ -172,6 +253,7 @@ RSpec.shared_examples 'a Collection indexer' do
172
253
  it_behaves_like 'a Core metadata indexer'
173
254
  it_behaves_like 'a permission indexer'
174
255
  it_behaves_like 'a visibility indexer'
256
+ it_behaves_like 'a thumbnail indexer'
175
257
 
176
258
  describe '#to_solr' do
177
259
  it 'indexes collection type gid' do
@@ -184,15 +266,47 @@ RSpec.shared_examples 'a Collection indexer' do
184
266
  .to include(generic_type_sim: a_collection_containing_exactly('Collection'))
185
267
  end
186
268
 
269
+ it 'indexes depositor' do
270
+ expect(indexer.to_solr)
271
+ .to include(depositor_ssim: [resource.depositor],
272
+ depositor_tesim: [resource.depositor])
273
+ end
274
+ end
275
+ end
276
+
277
+ RSpec.shared_examples 'an Administrative Set indexer' do
278
+ before do
279
+ raise 'indexer_class must be set with `let(:indexer_class)`' unless defined? indexer_class
280
+ # NOTE: resource must be persisted for permission tests to pass
281
+ raise 'resource must be set with `let(:resource)` and is expected to be a kind of Hyrax::AdministrativeSet' unless defined?(resource) && resource.kind_of?(Hyrax::AdministrativeSet)
282
+ end
283
+ subject(:indexer) { indexer_class.new(resource: resource) }
284
+
285
+ it_behaves_like 'a Hyrax::Resource indexer'
286
+ it_behaves_like 'a Core metadata indexer'
287
+ it_behaves_like 'a permission indexer'
288
+ it_behaves_like 'a visibility indexer'
289
+
290
+ describe '#to_solr' do
291
+ it 'indexes collection type gid' do
292
+ expect(indexer.to_solr)
293
+ .to include(collection_type_gid_ssim: a_collection_containing_exactly(an_instance_of(String)))
294
+ end
295
+
296
+ it 'indexes generic type' do
297
+ expect(indexer.to_solr)
298
+ .to include(generic_type_sim: a_collection_containing_exactly('Admin Set'))
299
+ end
300
+
187
301
  it 'indexes thumbnail' do
188
302
  expect(indexer.to_solr)
189
303
  .to include(thumbnail_path_ss: include('assets/collection', '.png'))
190
304
  end
191
305
 
192
- it 'indexes depositor' do
306
+ it 'indexes creator' do
193
307
  expect(indexer.to_solr)
194
- .to include(depositor_ssim: [resource.depositor],
195
- depositor_tesim: [resource.depositor])
308
+ .to include(creator_ssim: [resource.creator],
309
+ creator_tesim: [resource.creator])
196
310
  end
197
311
  end
198
312
  end
@@ -8,7 +8,8 @@ module Hyrax
8
8
  #
9
9
  # @since 3.2.0
10
10
  class AdminSetCreate < Transaction
11
- DEFAULT_STEPS = ['change_set.apply',
11
+ DEFAULT_STEPS = ['change_set.set_user_as_creator',
12
+ 'change_set.apply',
12
13
  'admin_set_resource.apply_collection_type_permissions',
13
14
  'admin_set_resource.save_acl'].freeze
14
15
 
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require 'hyrax/transactions/transaction'
3
+
4
+ module Hyrax
5
+ module Transactions
6
+ ##
7
+ # Destroys a {Hyraxe::AdministrativeSet}
8
+ #
9
+ # @since 3.4.0
10
+ class AdminSetDestroy < Transaction
11
+ DEFAULT_STEPS = ['admin_set_resource.check_empty',
12
+ 'admin_set_resource.delete',
13
+ 'admin_set_resource.delete_acl'].freeze
14
+
15
+ ##
16
+ # @see Hyrax::Transactions::Transaction
17
+ def initialize(container: Container, steps: DEFAULT_STEPS)
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ require 'hyrax/transactions/transaction'
3
+
4
+ module Hyrax
5
+ module Transactions
6
+ ##
7
+ # Updates a {Hyrax::AdministrativeSet} from a ChangeSet
8
+ #
9
+ # @since 3.4.0
10
+ class AdminSetUpdate < Transaction
11
+ DEFAULT_STEPS = ['change_set.apply',
12
+ 'admin_set_resource.save_acl'].freeze
13
+
14
+ ##
15
+ # @see Hyrax::Transactions::Transaction
16
+ def initialize(container: Container, steps: DEFAULT_STEPS)
17
+ super
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require 'hyrax/transactions/transaction'
3
+
4
+ module Hyrax
5
+ module Transactions
6
+ ##
7
+ # Destroys a {Hyrax::PcdmCollection}
8
+ #
9
+ # @since 3.4.0
10
+ class CollectionDestroy < Transaction
11
+ # TODO: Add step that checks if collection is empty for collections of types that require it
12
+ DEFAULT_STEPS = ['collection_resource.delete',
13
+ 'collection_resource.delete_acl'].freeze
14
+
15
+ ##
16
+ # @see Hyrax::Transactions::Transaction
17
+ def initialize(container: Container, steps: DEFAULT_STEPS)
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
@@ -4,11 +4,12 @@ require 'hyrax/transactions/transaction'
4
4
  module Hyrax
5
5
  module Transactions
6
6
  ##
7
- # Creates a Collection from a ChangeSet
7
+ # Updates a Collection from a ChangeSet
8
8
  #
9
9
  # @since 3.2.0
10
10
  class CollectionUpdate < Transaction
11
- DEFAULT_STEPS = ['change_set.apply'].freeze
11
+ DEFAULT_STEPS = ['change_set.apply',
12
+ 'collection_resource.save_acl'].freeze
12
13
 
13
14
  ##
14
15
  # @see Hyrax::Transactions::Transaction
@@ -10,51 +10,62 @@ module Hyrax
10
10
  #
11
11
  # In advanced use, the container could provide runtime dependency injection
12
12
  # for particular step code. For the basic case, users can consider it as
13
- # providing namespaceing and resolution for steps (as used in
14
- # `Hyrax::Transaction::CreateWork`; e.g.
15
- # `step :save_work, with: 'work.save_work'`).
13
+ # providing namespacing and resolution for steps (as used in
14
+ # `Hyrax::Transaction::WorkCreate`; e.g.
15
+ # `step :save, with: 'work_resource.save'`).
16
16
  #
17
17
  # @since 2.4.0
18
18
  #
19
19
  # @see https://dry-rb.org/gems/dry-container/
20
20
  class Container # rubocop:disable Metrics/ClassLength
21
21
  require 'hyrax/transactions/admin_set_create'
22
+ require 'hyrax/transactions/admin_set_destroy'
23
+ require 'hyrax/transactions/admin_set_update'
22
24
  require 'hyrax/transactions/apply_change_set'
23
25
  require 'hyrax/transactions/collection_create'
26
+ require 'hyrax/transactions/collection_destroy'
24
27
  require 'hyrax/transactions/collection_update'
25
- require 'hyrax/transactions/create_work'
26
- require 'hyrax/transactions/destroy_work'
27
28
  require 'hyrax/transactions/file_set_destroy'
28
29
  require 'hyrax/transactions/work_create'
29
30
  require 'hyrax/transactions/work_destroy'
30
- require 'hyrax/transactions/update_work'
31
+ require 'hyrax/transactions/work_update'
31
32
  require 'hyrax/transactions/steps/add_file_sets'
32
33
  require 'hyrax/transactions/steps/add_to_collections'
33
34
  require 'hyrax/transactions/steps/add_to_parent'
34
- require 'hyrax/transactions/steps/apply_collection_permission_template'
35
35
  require 'hyrax/transactions/steps/apply_collection_type_permissions'
36
- require 'hyrax/transactions/steps/apply_permission_template'
37
- require 'hyrax/transactions/steps/apply_visibility'
36
+ require 'hyrax/transactions/steps/change_depositor'
37
+ require 'hyrax/transactions/steps/check_for_empty_admin_set'
38
+ require 'hyrax/transactions/steps/delete_access_control'
38
39
  require 'hyrax/transactions/steps/delete_resource'
39
- require 'hyrax/transactions/steps/destroy_work'
40
40
  require 'hyrax/transactions/steps/ensure_admin_set'
41
41
  require 'hyrax/transactions/steps/set_collection_type_gid'
42
- require 'hyrax/transactions/steps/ensure_permission_template'
43
42
  require 'hyrax/transactions/steps/remove_file_set_from_work'
44
43
  require 'hyrax/transactions/steps/save'
45
- require 'hyrax/transactions/steps/save_work'
46
44
  require 'hyrax/transactions/steps/save_access_control'
47
45
  require 'hyrax/transactions/steps/set_default_admin_set'
48
46
  require 'hyrax/transactions/steps/set_modified_date'
49
47
  require 'hyrax/transactions/steps/set_uploaded_date_unless_present'
48
+ require 'hyrax/transactions/steps/set_user_as_creator'
50
49
  require 'hyrax/transactions/steps/set_user_as_depositor'
50
+ require 'hyrax/transactions/steps/update_work_members'
51
51
  require 'hyrax/transactions/steps/validate'
52
52
 
53
+ # The following transactions and steps are deprecated.
54
+ require 'hyrax/transactions/create_work'
55
+ require 'hyrax/transactions/destroy_work'
56
+ require 'hyrax/transactions/update_work'
57
+ require 'hyrax/transactions/steps/apply_collection_permission_template'
58
+ require 'hyrax/transactions/steps/apply_permission_template'
59
+ require 'hyrax/transactions/steps/apply_visibility'
60
+ require 'hyrax/transactions/steps/destroy_work'
61
+ require 'hyrax/transactions/steps/ensure_permission_template'
62
+ require 'hyrax/transactions/steps/save_work'
63
+
53
64
  extend Dry::Container::Mixin
54
65
 
55
66
  # Disable BlockLength rule for DSL code
56
67
  # rubocop:disable Metrics/BlockLength
57
- namespace 'change_set' do |ops|
68
+ namespace 'change_set' do |ops| # Hyrax::ChangeSet
58
69
  ops.register 'add_to_collections' do
59
70
  Steps::AddToCollections.new
60
71
  end
@@ -63,12 +74,12 @@ module Hyrax
63
74
  ApplyChangeSet.new
64
75
  end
65
76
 
66
- ops.register 'create_collection' do
67
- CollectionCreate.new
77
+ ops.register 'create_admin_set' do
78
+ AdminSetCreate.new
68
79
  end
69
80
 
70
- ops.register 'update_collection' do
71
- CollectionUpdate.new
81
+ ops.register 'create_collection' do
82
+ CollectionCreate.new
72
83
  end
73
84
 
74
85
  ops.register 'create_work' do
@@ -99,12 +110,20 @@ module Hyrax
99
110
  Steps::SetUploadedDateUnlessPresent.new
100
111
  end
101
112
 
113
+ ops.register 'set_user_as_creator' do
114
+ Steps::SetUserAsCreator.new
115
+ end
116
+
102
117
  ops.register 'set_user_as_depositor' do
103
118
  Steps::SetUserAsDepositor.new
104
119
  end
105
120
 
121
+ ops.register 'update_collection' do
122
+ CollectionUpdate.new
123
+ end
124
+
106
125
  ops.register 'update_work' do
107
- UpdateWork.new
126
+ WorkUpdate.new
108
127
  end
109
128
 
110
129
  ops.register 'validate' do
@@ -112,7 +131,7 @@ module Hyrax
112
131
  end
113
132
  end
114
133
 
115
- namespace 'file_set' do |ops| # Hyrax::FileSet
134
+ namespace 'file_set' do |ops| # Hyrax::FileSet resource
116
135
  ops.register 'delete' do
117
136
  Steps::DeleteResource.new
118
137
  end
@@ -126,27 +145,59 @@ module Hyrax
126
145
  end
127
146
  end
128
147
 
129
- namespace 'admin_set_resource' do |ops| # valkyrie administrative set
148
+ namespace 'admin_set_resource' do |ops| # Hyrax::AdministrativeSet resource
149
+ ops.register 'check_empty' do
150
+ Steps::CheckForEmptyAdminSet.new
151
+ end
152
+
153
+ ops.register 'delete' do
154
+ Steps::DeleteResource.new
155
+ end
156
+
157
+ ops.register 'destroy' do
158
+ AdminSetDestroy.new
159
+ end
160
+
161
+ ops.register 'update' do
162
+ AdminSetUpdate.new
163
+ end
164
+
130
165
  ops.register 'apply_collection_type_permissions' do
131
166
  Steps::ApplyCollectionTypePermissions.new
132
167
  end
133
168
 
169
+ ops.register 'delete_acl' do
170
+ Steps::DeleteAccessControl.new
171
+ end
172
+
134
173
  ops.register 'save_acl' do
135
174
  Steps::SaveAccessControl.new
136
175
  end
137
176
  end
138
177
 
139
- namespace 'collection_resource' do |ops| # valkyrie collection
178
+ namespace 'collection_resource' do |ops| # Hyrax::PcdmCollection resource
140
179
  ops.register 'apply_collection_type_permissions' do
141
180
  Steps::ApplyCollectionTypePermissions.new
142
181
  end
143
182
 
183
+ ops.register 'delete' do
184
+ Steps::DeleteResource.new
185
+ end
186
+
187
+ ops.register 'destroy' do
188
+ CollectionDestroy.new
189
+ end
190
+
191
+ ops.register 'delete_acl' do
192
+ Steps::DeleteAccessControl.new
193
+ end
194
+
144
195
  ops.register 'save_acl' do
145
196
  Steps::SaveAccessControl.new
146
197
  end
147
198
  end
148
199
 
149
- namespace 'work_resource' do |ops| # valkyrie works
200
+ namespace 'work_resource' do |ops| # Hyrax::Work resource
150
201
  ops.register 'add_file_sets' do
151
202
  Steps::AddFileSets.new
152
203
  end
@@ -155,6 +206,10 @@ module Hyrax
155
206
  Steps::AddToParent.new
156
207
  end
157
208
 
209
+ ops.register 'change_depositor' do
210
+ Steps::ChangeDepositor.new
211
+ end
212
+
158
213
  ops.register 'delete' do
159
214
  Steps::DeleteResource.new
160
215
  end
@@ -163,12 +218,21 @@ module Hyrax
163
218
  WorkDestroy.new
164
219
  end
165
220
 
221
+ ops.register 'delete_acl' do
222
+ Steps::DeleteAccessControl.new
223
+ end
224
+
166
225
  ops.register 'save_acl' do
167
226
  Steps::SaveAccessControl.new
168
227
  end
228
+
229
+ ops.register 'update_work_members' do
230
+ Steps::UpdateWorkMembers.new
231
+ end
169
232
  end
170
233
 
171
- namespace 'work' do |ops| # legacy AF works
234
+ # legacy AF works processing by transactions is deprecated
235
+ namespace 'work' do |ops|
172
236
  ops.register 'apply_collection_permission_template' do
173
237
  Steps::ApplyCollectionPermissionTemplate.new
174
238
  end
@@ -46,9 +46,12 @@ module Hyrax
46
46
  # @deprecated Development on Dry::Transaction has been discontinued, we're
47
47
  # removing existing transactions and replacing them with Dry::Monad-based
48
48
  # valkyrie versions.
49
+ # @see Hyrax::Transactions::WorkCreate
49
50
  class CreateWork
50
51
  include Dry::Transaction(container: Hyrax::Transactions::Container)
51
52
 
53
+ # DO NOT USE - This class is deprecated. See Hyrax::Transactions::WorkCreate for resource works.
54
+
52
55
  step :set_default_admin_set, with: 'work.set_default_admin_set'
53
56
  step :ensure_admin_set, with: 'work.ensure_admin_set'
54
57
  step :apply_permission_template, with: 'work.apply_permission_template'
@@ -16,9 +16,12 @@ module Hyrax
16
16
  # @deprecated Development on Dry::Transaction has been discontinued, we're
17
17
  # removing existing transactions and replacing them with Dry::Monad-based
18
18
  # valkyrie versions.
19
+ # @see Hyrax::Transactions::WorkDestroy
19
20
  class DestroyWork
20
21
  include Dry::Transaction(container: Hyrax::Transactions::Container)
21
22
 
23
+ # DO NOT USE - This class is deprecated. See Hyrax::Transactions::WorkDestroy for resource works.
24
+
22
25
  step :destroy_work, with: 'work.destroy_work'
23
26
  end
24
27
  end