hyrax 5.0.0.rc1 → 5.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +11 -4
  3. data/.dassie/.env +5 -1
  4. data/.dassie/Gemfile +27 -42
  5. data/.dassie/Gemfile.dassie +2 -0
  6. data/.dassie/app/assets/config/manifest.js +2 -0
  7. data/.dassie/app/assets/stylesheets/hyrax.scss +1 -0
  8. data/.dassie/config/initializers/riiif.rb +5 -11
  9. data/.dassie/config/metadata/collection_resource.yaml +3 -0
  10. data/.dassie/config/metadata/monograph.yaml +8 -0
  11. data/.dassie/config/metadata/sample_metadata.yaml +1 -0
  12. data/.dassie/config/redis.yml +2 -0
  13. data/.dassie/db/migrate/20230725222727_create_hyrax_counter_metrics.hyrax.rb +14 -0
  14. data/.dassie/db/migrate/20230803165135_change_work_id_to_string.rb +5 -0
  15. data/.dassie/db/migrate/20230808102105_add_indices_to_hyrax_counter_metrics.hyrax.rb +8 -0
  16. data/.dassie/db/migrate/20230821153635_add_fields_to_counter_metric.rb +8 -0
  17. data/.dassie/db/schema.rb +20 -1
  18. data/.dockerignore +2 -1
  19. data/.gitignore +1 -1
  20. data/.koppie/.env +10 -4
  21. data/.koppie/Gemfile +10 -12
  22. data/.koppie/Gemfile.koppie +2 -0
  23. data/.koppie/Rakefile +0 -2
  24. data/.koppie/app/forms/collection_resource_form.rb +0 -1
  25. data/.koppie/app/indexers/collection_resource_indexer.rb +0 -1
  26. data/.koppie/app/models/ability.rb +1 -5
  27. data/.koppie/app/models/collection_resource.rb +0 -1
  28. data/.koppie/app/models/user.rb +0 -2
  29. data/.koppie/config/application.rb +2 -1
  30. data/.koppie/config/arkivo.yml +6 -0
  31. data/.koppie/config/blacklight.yml +2 -2
  32. data/.koppie/config/features.yml +2 -0
  33. data/.koppie/config/initializers/1_valkyrie.rb +29 -6
  34. data/.koppie/config/initializers/arkivo_constraint.rb +12 -0
  35. data/.koppie/config/initializers/hyrax.rb +2 -2
  36. data/.koppie/config/initializers/riiif.rb +6 -11
  37. data/.koppie/config/metadata/collection_resource.yaml +177 -1
  38. data/.koppie/config/metadata/generic_work.yaml +2 -0
  39. data/.koppie/config/metadata/monograph.yaml +10 -0
  40. data/.koppie/config/role_map.yml +3 -25
  41. data/.koppie/config/routes.rb +1 -2
  42. data/.koppie/config/solr.yml +1 -1
  43. data/.koppie/config/valkyrie_index.yml +4 -10
  44. data/.koppie/config/zotero.yml +6 -0
  45. data/.koppie/db/migrate/20230725222727_create_hyrax_counter_metrics.hyrax.rb +14 -0
  46. data/.koppie/db/migrate/20230803165135_change_work_id_to_string.rb +5 -0
  47. data/.koppie/db/schema.rb +12 -1
  48. data/CONTAINERS.md +1 -3
  49. data/Dockerfile +11 -2
  50. data/Gemfile +4 -21
  51. data/Gemfile.dassie +2 -0
  52. data/Gemfile.koppie +2 -0
  53. data/README.md +0 -1
  54. data/Rakefile +0 -11
  55. data/app/actors/hyrax/actors/embargo_actor.rb +3 -6
  56. data/app/assets/javascripts/hyrax/batch_select_all.js +1 -1
  57. data/app/assets/javascripts/hyrax/file_manager/member.es6 +1 -1
  58. data/app/assets/stylesheets/hyrax/_file-listing.scss +0 -2
  59. data/app/assets/stylesheets/hyrax/_work-show.scss +19 -3
  60. data/app/assets/stylesheets/hyrax/sidebar.scss +23 -0
  61. data/app/controllers/concerns/hyrax/embargoes_controller_behavior.rb +7 -1
  62. data/app/controllers/concerns/hyrax/leases_controller_behavior.rb +7 -1
  63. data/app/controllers/concerns/hyrax/valkyrie_downloads_controller_behavior.rb +14 -9
  64. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +50 -9
  65. data/app/controllers/hyrax/api/items_controller.rb +2 -3
  66. data/app/controllers/hyrax/batch_edits_controller.rb +6 -6
  67. data/app/controllers/hyrax/batch_uploads_controller.rb +5 -1
  68. data/app/controllers/hyrax/dashboard/collections_controller.rb +4 -1
  69. data/app/controllers/hyrax/file_sets_controller.rb +49 -6
  70. data/app/controllers/hyrax/my/collections_controller.rb +2 -0
  71. data/app/controllers/hyrax/single_use_links_viewer_controller.rb +16 -2
  72. data/app/forms/concerns/hyrax/basic_metadata_form_fields_behavior.rb +38 -0
  73. data/app/forms/hyrax/forms/collection_form.rb +0 -15
  74. data/app/forms/hyrax/forms/dashboard/nest_collection_form.rb +0 -34
  75. data/app/forms/hyrax/forms/file_set_form.rb +2 -2
  76. data/app/forms/hyrax/forms/pcdm_object_form.rb +21 -0
  77. data/app/forms/hyrax/forms/permission_template_form.rb +0 -7
  78. data/app/forms/hyrax/forms/resource_batch_edit_form.rb +49 -21
  79. data/app/forms/hyrax/forms/resource_form.rb +21 -34
  80. data/app/helpers/hyrax/dashboard_helper_behavior.rb +13 -0
  81. data/app/indexers/hyrax/location_indexer.rb +29 -0
  82. data/app/indexers/hyrax/pcdm_collection_indexer.rb +0 -8
  83. data/app/indexers/hyrax/valkyrie_file_set_indexer.rb +1 -6
  84. data/app/indexers/hyrax/valkyrie_work_indexer.rb +1 -0
  85. data/app/inputs/controlled_vocabulary_input.rb +1 -1
  86. data/app/jobs/characterize_job.rb +1 -1
  87. data/app/jobs/create_work_job.rb +36 -4
  88. data/app/jobs/valkyrie_characterization_job.rb +9 -0
  89. data/app/jobs/valkyrie_ingest_job.rb +1 -3
  90. data/app/models/collection_branding_info.rb +2 -9
  91. data/app/models/concerns/hyrax/ability.rb +2 -1
  92. data/app/models/concerns/hyrax/collection_behavior.rb +4 -12
  93. data/app/models/concerns/hyrax/riiif_file.rb +30 -0
  94. data/app/models/concerns/hyrax/solr_document_behavior.rb +19 -2
  95. data/app/models/hyrax/counter_metric.rb +7 -0
  96. data/app/models/hyrax/file_metadata.rb +3 -2
  97. data/app/models/hyrax/file_set.rb +75 -22
  98. data/app/models/hyrax/orcid_validator.rb +0 -6
  99. data/app/models/hyrax/work.rb +2 -5
  100. data/app/presenters/hyrax/collection_presenter.rb +0 -17
  101. data/app/presenters/hyrax/embargo_presenter.rb +4 -0
  102. data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +6 -4
  103. data/app/presenters/hyrax/version_list_presenter.rb +19 -10
  104. data/app/presenters/hyrax/version_presenter.rb +19 -4
  105. data/app/services/hyrax/admin_set_create_service.rb +0 -17
  106. data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +5 -0
  107. data/app/services/hyrax/collections/collection_member_service.rb +1 -1
  108. data/app/services/hyrax/embargo_manager.rb +45 -18
  109. data/app/services/hyrax/embargo_service.rb +12 -10
  110. data/app/services/hyrax/file_set_derivatives_service.rb +11 -11
  111. data/app/services/hyrax/fixity_check_failure_service.rb +1 -1
  112. data/app/services/hyrax/identifier/dispatcher.rb +9 -2
  113. data/app/services/hyrax/listeners/file_metadata_listener.rb +14 -6
  114. data/app/services/hyrax/listeners/member_cleanup_listener.rb +2 -28
  115. data/app/services/hyrax/listeners/metadata_index_listener.rb +11 -0
  116. data/app/services/hyrax/lock_manager.rb +1 -2
  117. data/app/services/hyrax/riiif_file_resolver.rb +50 -0
  118. data/app/services/hyrax/simple_schema_loader.rb +31 -0
  119. data/app/services/hyrax/valkyrie_persist_derivatives.rb +1 -1
  120. data/app/services/hyrax/valkyrie_upload.rb +12 -26
  121. data/app/services/hyrax/versioning_service.rb +29 -15
  122. data/app/services/hyrax/work_uploads_handler.rb +1 -1
  123. data/app/validators/hyrax/collection_membership_validator.rb +1 -1
  124. data/app/views/catalog/_search_form.html.erb +1 -1
  125. data/app/views/hyrax/admin/collection_types/index.html.erb +1 -1
  126. data/app/views/hyrax/base/_file_manager_resource_form.html.erb +1 -1
  127. data/app/views/hyrax/base/_form_visibility_component.html.erb +4 -4
  128. data/app/views/hyrax/base/_show_actions.html.erb +1 -1
  129. data/app/views/hyrax/base/_workflow_actions.html.erb +25 -23
  130. data/app/views/hyrax/base/show.json.jbuilder +2 -1
  131. data/app/views/hyrax/collections/_show_document_list_row.html.erb +1 -1
  132. data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +1 -1
  133. data/app/views/hyrax/dashboard/collections/_show_document_list_row.html.erb +1 -1
  134. data/app/views/hyrax/dashboard/collections/_sort_and_per_page.html.erb +3 -3
  135. data/app/views/hyrax/file_sets/_versioning.html.erb +5 -5
  136. data/app/views/hyrax/file_sets/media_display/_audio.html.erb +4 -4
  137. data/app/views/hyrax/file_sets/media_display/_default.html.erb +1 -1
  138. data/app/views/hyrax/file_sets/media_display/_video.html.erb +2 -2
  139. data/app/views/hyrax/my/_search_form.html.erb +1 -1
  140. data/app/views/hyrax/notifications/_notifications.html.erb +1 -1
  141. data/app/views/hyrax/users/_vitals.html.erb +1 -1
  142. data/bin/dev-entrypoint.sh +13 -0
  143. data/chart/hyrax/Chart.yaml +3 -3
  144. data/chart/hyrax/templates/_helpers.tpl +8 -0
  145. data/chart/hyrax/templates/configmap-env.yaml +1 -1
  146. data/chart/hyrax/values.yaml +3 -0
  147. data/config/initializers/file_length_patch.rb +10 -0
  148. data/config/metadata/basic_metadata.yaml +52 -0
  149. data/config/metadata/core_metadata.yaml +4 -0
  150. data/config/metadata/file_set_metadata.yaml +19 -0
  151. data/config/metadata/hyrax_internal_metadata.yaml +57 -0
  152. data/docker-compose-koppie.yml +23 -22
  153. data/docker-compose-sirenia.yml +202 -0
  154. data/docker-compose.yml +27 -24
  155. data/documentation/developing-your-hyrax-based-app.md +2 -2
  156. data/hyrax.gemspec +10 -11
  157. data/karma.conf.js +1 -1
  158. data/lib/generators/hyrax/collection_resource/templates/collection_metadata.yaml +2 -0
  159. data/lib/generators/hyrax/templates/config/initializers/riiif.rb +13 -19
  160. data/lib/generators/hyrax/templates/db/migrate/20230725222727_create_hyrax_counter_metrics.rb.erb +14 -0
  161. data/lib/generators/hyrax/templates/db/migrate/20230803165135_change_work_id_to_string.rb.erb +5 -0
  162. data/lib/generators/hyrax/templates/db/migrate/20230808102105_add_indices_to_hyrax_counter_metrics.rb.erb +8 -0
  163. data/lib/generators/hyrax/templates/db/migrate/20230821153635_add_fields_to_counter_metric.rb.erb +8 -0
  164. data/lib/generators/hyrax/templates/db/seeds.rb +1 -1
  165. data/lib/generators/hyrax/work_resource/templates/form.rb.erb +1 -1
  166. data/lib/generators/hyrax/work_resource/templates/metadata.yaml +2 -0
  167. data/lib/hyrax/configuration.rb +147 -49
  168. data/lib/hyrax/controlled_vocabularies/location.rb +7 -1
  169. data/lib/hyrax/engine.rb +0 -1
  170. data/lib/hyrax/form_fields.rb +6 -0
  171. data/lib/hyrax/publisher.rb +4 -0
  172. data/lib/hyrax/redis_event_store.rb +7 -8
  173. data/lib/hyrax/resource_name.rb +4 -0
  174. data/lib/hyrax/specs/capybara.rb +25 -42
  175. data/lib/hyrax/specs/shared_specs/hydra_works.rb +34 -7
  176. data/lib/hyrax/specs/shared_specs/indexers.rb +24 -6
  177. data/lib/hyrax/transactions/collection_destroy.rb +3 -2
  178. data/lib/hyrax/transactions/container.rb +42 -0
  179. data/lib/hyrax/transactions/file_metadata_destroy.rb +20 -0
  180. data/lib/hyrax/transactions/file_set_destroy.rb +3 -1
  181. data/lib/hyrax/transactions/file_set_update.rb +21 -0
  182. data/lib/hyrax/transactions/steps/add_to_parent.rb +1 -1
  183. data/lib/hyrax/transactions/steps/delete_all_file_metadata.rb +46 -0
  184. data/lib/hyrax/transactions/steps/delete_all_file_sets.rb +46 -0
  185. data/lib/hyrax/transactions/steps/file_metadata_delete.rb +40 -0
  186. data/lib/hyrax/transactions/steps/remove_from_membership.rb +45 -0
  187. data/lib/hyrax/transactions/work_destroy.rb +3 -2
  188. data/lib/hyrax/version.rb +1 -1
  189. data/lib/tasks/collection_type_global_id.rake +9 -4
  190. data/lib/tasks/embargo_lease.rake +1 -0
  191. data/lib/valkyrie/indexing/solr/indexing_adapter.rb +2 -0
  192. data/lib/wings/active_fedora_converter.rb +6 -0
  193. data/lib/wings/attribute_transformer.rb +24 -17
  194. data/lib/wings/model_transformer.rb +0 -8
  195. data/lib/wings/orm_converter.rb +23 -18
  196. data/lib/wings/setup.rb +2 -2
  197. data/lib/wings/valkyrie/storage.rb +8 -90
  198. data/lib/wings.rb +5 -0
  199. data/tasks/hyrax_dev.rake +2 -33
  200. data/template.rb +1 -1
  201. metadata +90 -72
  202. data/.engine_cart.yml +0 -3
  203. data/app/views/hyrax/users/_user_util_links_extra.html.erb +0 -0
  204. data/lib/hyrax/specs/shared_specs/valkyrie_storage_versions.rb +0 -9
@@ -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::FileSet} from a ChangeSet
8
+ #
9
+ # @since 3.4.0
10
+ class FileSetUpdate < Transaction
11
+ DEFAULT_STEPS = ['change_set.apply',
12
+ 'file_set.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
@@ -20,7 +20,7 @@ module Hyrax
20
20
  return Success(obj) if parent_id.blank?
21
21
 
22
22
  parent = Hyrax.query_service.find_by(id: parent_id)
23
- parent.member_ids << obj.id
23
+ parent.member_ids += [obj.id]
24
24
  Hyrax.persister.save(resource: parent)
25
25
 
26
26
  user ||= ::User.find_by_user_key(obj.depositor)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ require 'dry/monads'
3
+
4
+ module Hyrax
5
+ module Transactions
6
+ module Steps
7
+ ##
8
+ # Deletes a resource from the persister, returning a `Dry::Monads::Result`
9
+ # (`Success`|`Failure`).
10
+ #
11
+ # @see https://dry-rb.org/gems/dry-monads/1.0/result/
12
+ class DeleteAllFileMetadata
13
+ include Dry::Monads[:result]
14
+
15
+ ##
16
+ # @params [#save] persister
17
+ def initialize(property: :file_ids, query_service: Hyrax.query_service, persister: Hyrax.persister, publisher: Hyrax.publisher)
18
+ @property = property
19
+ @persister = persister
20
+ @query_service = query_service
21
+ @publisher = publisher
22
+ end
23
+
24
+ ##
25
+ # @param [Valkyrie::Resource] resource
26
+ # @param [::User] the user resposible for the delete action
27
+ #
28
+ # @return [Dry::Monads::Result]
29
+ def call(resource)
30
+ return Failure(:resource_not_persisted) unless resource.persisted?
31
+
32
+ resource[@property].each do |file_id|
33
+ return Failure[:failed_to_delete_file_metadata, file_id] unless
34
+ Hyrax::Transactions::Container['file_metadata.destroy']
35
+ .call(@query_service.custom_queries.find_file_metadata_by(id: file_id))
36
+ .success?
37
+ rescue ::Ldp::Gone
38
+ nil
39
+ end
40
+
41
+ Success(resource)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ require 'dry/monads'
3
+
4
+ module Hyrax
5
+ module Transactions
6
+ module Steps
7
+ ##
8
+ # Deletes a resource's member FileSets from the persister, returning a `Dry::Monads::Result`
9
+ # (`Success`|`Failure`).
10
+ #
11
+ # @see https://dry-rb.org/gems/dry-monads/1.0/result/
12
+ class DeleteAllFileSets
13
+ include Dry::Monads[:result]
14
+
15
+ ##
16
+ # @params [#save] persister
17
+ def initialize(query_service: Hyrax.query_service, persister: Hyrax.persister, publisher: Hyrax.publisher)
18
+ @persister = persister
19
+ @query_service = query_service
20
+ @publisher = publisher
21
+ end
22
+
23
+ ##
24
+ # @param [Valkyrie::Resource] resource
25
+ # @param [::User] the user resposible for the delete action
26
+ #
27
+ # @return [Dry::Monads::Result]
28
+ def call(resource, user: nil)
29
+ return Failure(:resource_not_persisted) unless resource.persisted?
30
+
31
+ @query_service.custom_queries.find_child_file_sets(resource: resource).each do |file_set|
32
+ return Failure[:failed_to_delete_file_set, file_set] unless
33
+ Hyrax::Transactions::Container['file_set.destroy']
34
+ .with_step_args('file_set.remove_from_work' => { user: user },
35
+ 'file_set.delete' => { user: user })
36
+ .call(file_set).success?
37
+ rescue ::Ldp::Gone
38
+ nil
39
+ end
40
+
41
+ Success(resource)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ require 'dry/monads'
3
+
4
+ module Hyrax
5
+ module Transactions
6
+ module Steps
7
+ ##
8
+ # Deletes a resource from the persister, returning a `Dry::Monads::Result`
9
+ # (`Success`|`Failure`).
10
+ #
11
+ # @see https://dry-rb.org/gems/dry-monads/1.0/result/
12
+ class FileMetadataDelete
13
+ include Dry::Monads[:result]
14
+
15
+ ##
16
+ # @params [#save] persister
17
+ def initialize(persister: Hyrax.persister, storage_adapter: Hyrax.storage_adapter, publisher: Hyrax.publisher)
18
+ @persister = persister
19
+ @publisher = publisher
20
+ @storage_adapter = storage_adapter
21
+ end
22
+
23
+ ##
24
+ # @param [Hyrax::FileMetadata] FileMetadata resource
25
+ # @param [::User] the user resposible for the delete action
26
+ #
27
+ # @return [Dry::Monads::Result]
28
+ def call(resource)
29
+ return Failure(:resource_not_persisted) unless resource.persisted?
30
+
31
+ @persister.delete(resource: resource)
32
+ @publisher.publish('file.metadata.deleted', metadata: resource)
33
+ Valkyrie::StorageAdapter.delete(id: resource.file_identifier) if resource.file_identifier.present?
34
+
35
+ Success(resource)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ require 'dry/monads'
3
+
4
+ module Hyrax
5
+ module Transactions
6
+ module Steps
7
+ ##
8
+ # Removes a collection from its members, returning a `Dry::Monads::Result`
9
+ # (`Success`|`Failure`).
10
+ #
11
+ # @see https://dry-rb.org/gems/dry-monads/1.0/result/
12
+ class RemoveFromMembership
13
+ include Dry::Monads[:result]
14
+
15
+ ##
16
+ # @params [#save] persister
17
+ def initialize(query_service: Hyrax.custom_queries, persister: Hyrax.persister, publisher: Hyrax.publisher)
18
+ @persister = persister
19
+ @query_service = query_service
20
+ @publisher = publisher
21
+ end
22
+
23
+ ##
24
+ # @param [Valkyrie::Resource] resource
25
+ # @param [::User] the user resposible for the delete action
26
+ #
27
+ # @return [Dry::Monads::Result]
28
+ def call(collection, user: nil)
29
+ return Failure(:resource_not_persisted) unless collection.persisted?
30
+ return Failure(:user_not_present) if user.blank?
31
+
32
+ @query_service.find_members_of(collection: collection).each do |member|
33
+ member.member_of_collection_ids -= [collection.id]
34
+ @persister.save(resource: member)
35
+ @publisher.publish('collection.membership.updated', collection: collection, user: user)
36
+ rescue StandardError
37
+ nil
38
+ end
39
+
40
+ Success(collection)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -8,8 +8,9 @@ module Hyrax
8
8
  #
9
9
  # @since 3.0.0
10
10
  class WorkDestroy < Transaction
11
- DEFAULT_STEPS = ['work_resource.delete',
12
- 'work_resource.delete_acl'].freeze
11
+ DEFAULT_STEPS = ['work_resource.delete_all_file_sets',
12
+ 'work_resource.delete_acl',
13
+ 'work_resource.delete'].freeze
13
14
 
14
15
  ##
15
16
  # @see Hyrax::Transactions::Transaction
data/lib/hyrax/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Hyrax
3
- VERSION = '5.0.0.rc1'
3
+ VERSION = '5.0.0.rc2'
4
4
  end
@@ -7,13 +7,18 @@ namespace :hyrax do
7
7
 
8
8
  count = 0
9
9
 
10
- Collection.all.each do |collection|
11
- next if collection.collection_type_gid == collection.collection_type.to_global_id.to_s
10
+ Hyrax.query_service.find_all_of_model(model: Hyrax::PcdmCollection).each do |collection|
11
+ type = Hyrax::CollectionType.find_by_gid(collection.collection_type_gid)
12
+ next if collection.collection_type_gid == type.to_global_id.to_s
12
13
 
13
- collection.public_send(:collection_type_gid=, collection.collection_type.to_global_id, force: true)
14
+ # Awful hack to allow converted AF collections to force update collection_type_gid
15
+ Thread.current[:force_collection_type_gid] = true
16
+ collection.collection_type_gid = type.to_global_id
14
17
 
15
- collection.save &&
18
+ Hyrax.persister.save(resource: collection) &&
16
19
  count += 1
20
+ ensure
21
+ Thread.current[:force_collection_type_gid] = false
17
22
  end
18
23
 
19
24
  puts "Updated #{count} collections."
@@ -8,6 +8,7 @@ namespace :hyrax do
8
8
 
9
9
  Hyrax.query_service.find_many_by_ids(ids: ids).each do |resource|
10
10
  Hyrax::EmbargoManager.release_embargo_for(resource: resource) &&
11
+ Hyrax.persister.save(resource: resource.embargo) &&
11
12
  Hyrax::AccessControlList(resource).save
12
13
  end
13
14
  end
@@ -81,6 +81,8 @@ module Valkyrie
81
81
  # if any configuration is missing, derive it from Blacklight
82
82
  config = blacklight_based_config.with_indifferent_access.merge(config)
83
83
 
84
+ return config['url'] if config['url'].present?
85
+
84
86
  "http://#{config['host']}:#{config['port']}/solr/#{config['core']}"
85
87
  end
86
88
 
@@ -170,6 +170,7 @@ module Wings
170
170
 
171
171
  # for files, add attributes to metadata_node, plus some other work
172
172
  def add_file_attributes(af_object)
173
+ add_file_uri(af_object)
173
174
  converted_attrs = normal_attributes
174
175
  pcdm_use = converted_attrs.delete(:pcdm_use)
175
176
  af_object.metadata_node.attributes = converted_attrs
@@ -180,6 +181,11 @@ module Wings
180
181
  af_object.mime_type = resource.mime_type
181
182
  end
182
183
 
184
+ def add_file_uri(af_object)
185
+ file_uri = Hyrax.storage_adapter.fedora_identifier(id: resource.file_identifier)
186
+ af_object.uri = file_uri.to_s if af_object.uri.to_s.blank? && file_uri.to_s.present?
187
+ end
188
+
183
189
  def perform_lease_conversion(af_object:, resource:)
184
190
  # TODO(#6134): af_object.lease.class has the same name as resource.lease.class; however, each class has a different object_id
185
191
  # so a type mismatch happens. the code below coerces the one object into the other
@@ -15,29 +15,36 @@ module Wings
15
15
  end
16
16
  end
17
17
 
18
- def self.run(obj) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
19
- attrs = obj.reflections.each_with_object({}) do |(key, reflection), mem|
18
+ def self.run(obj) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
19
+ attrs = obj.reflections.each_with_object({}) do |(key, reflection), mem| # rubocop:disable Metrics/BlockLength
20
20
  case reflection
21
- when ActiveFedora::Reflection::HasManyReflection,
22
- ActiveFedora::Reflection::HasAndBelongsToManyReflection,
23
- ActiveFedora::Reflection::IndirectlyContainsReflection
24
- mem[:"#{key.to_s.singularize}_ids"] =
25
- obj.association(key).ids_reader
26
- when ActiveFedora::Reflection::DirectlyContainsReflection
27
- mem[:"#{key.to_s.singularize}_ids"] =
28
- Array(obj.public_send(reflection.name)).map(&:id)
29
- when ActiveFedora::Reflection::FilterReflection,
30
- ActiveFedora::Reflection::OrdersReflection,
31
- ActiveFedora::Reflection::HasSubresourceReflection,
32
- ActiveFedora::Reflection::BelongsToReflection,
33
- ActiveFedora::Reflection::BasicContainsReflection
21
+ when ActiveFedora::Reflection::BelongsToReflection, # uses foreign_key SingularRDFPropertyReflection
22
+ ActiveFedora::Reflection::BasicContainsReflection, # ???
23
+ ActiveFedora::Reflection::FilterReflection, # rely on :extending_from
24
+ ActiveFedora::Reflection::HasAndBelongsToManyReflection, # uses foreign_key RDFPropertyReflection
25
+ ActiveFedora::Reflection::HasManyReflection, # captured by inverse relation
26
+ ActiveFedora::Reflection::HasSubresourceReflection, # ???
34
27
  :noop
28
+ when ActiveFedora::Reflection::OrdersReflection
29
+ mem[:"#{reflection.options[:unordered_reflection].name.to_s.singularize}_ids"] ||= []
30
+ mem[:"#{reflection.options[:unordered_reflection].name.to_s.singularize}_ids"] +=
31
+ obj.association(reflection.name).target_ids_reader
35
32
  when ActiveFedora::Reflection::DirectlyContainsOneReflection
36
33
  mem[:"#{key.to_s.singularize}_id"] =
37
34
  obj.public_send(reflection.name)&.id
35
+ when ActiveFedora::Reflection::IndirectlyContainsReflection
36
+ mem[:"#{key.to_s.singularize}_ids"] ||= []
37
+ mem[:"#{key.to_s.singularize}_ids"] +=
38
+ obj.association(key).ids_reader
39
+ when ActiveFedora::Reflection::DirectlyContainsReflection
40
+ mem[:"#{key.to_s.singularize}_ids"] ||= []
41
+ mem[:"#{key.to_s.singularize}_ids"] +=
42
+ Array(obj.public_send(reflection.name)).map(&:id)
43
+ when ActiveFedora::Reflection::RDFPropertyReflection
44
+ mem[reflection.name.to_sym] =
45
+ obj.public_send(reflection.name.to_sym)
38
46
  else
39
- mem[reflection.foreign_key.to_sym] =
40
- obj.public_send(reflection.foreign_key.to_sym)
47
+ raise NotImplementedError, "Expected a known ActiveFedora::Reflection, but got #{reflection}"
41
48
  end
42
49
  end
43
50
 
@@ -150,17 +150,9 @@ module Wings
150
150
  { :id => pcdm_object.id,
151
151
  :created_at => pcdm_object.try(:create_date),
152
152
  :updated_at => pcdm_object.try(:modified_date),
153
- :member_ids => member_ids,
154
153
  ::Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK => lock_token }
155
154
  end
156
155
 
157
- # Prefer ordered members, but if ordered members don't exist, use non-ordered members.
158
- def member_ids
159
- ordered_member_ids = pcdm_object.try(:ordered_member_ids)
160
- return ordered_member_ids if ordered_member_ids.present?
161
- pcdm_object.try(:member_ids)
162
- end
163
-
164
156
  def lock_token
165
157
  result = []
166
158
  result << ::Valkyrie::Persistence::OptimisticLockToken.new(adapter_id: 'wings-fedora-etag', token: pcdm_object.etag) unless pcdm_object.new_record?
@@ -78,29 +78,34 @@ module Wings
78
78
  end
79
79
 
80
80
  # add reflection associations
81
- ldp_reflections = (klass.try(:reflections) || []).select do |_key, reflection|
81
+ (klass.try(:reflections) || []).each do |reflection_key, reflection|
82
82
  case reflection
83
- when ActiveFedora::Reflection::FilterReflection,
84
- ActiveFedora::Reflection::OrdersReflection,
85
- ActiveFedora::Reflection::BasicContainsReflection,
86
- ActiveFedora::Reflection::HasSubresourceReflection
87
- false
88
- else
89
- true
90
- end
91
- end
92
-
93
- ldp_reflections.each do |reflection_key, reflection|
94
- if reflection.collection?
95
- type = ::Valkyrie::Types::Set.of(::Valkyrie::Types::ID)
83
+ when ActiveFedora::Reflection::BelongsToReflection, # uses foreign_key SingularRDFPropertyReflection
84
+ ActiveFedora::Reflection::BasicContainsReflection, # ???
85
+ ActiveFedora::Reflection::FilterReflection, # rely on :extending_from
86
+ ActiveFedora::Reflection::HasAndBelongsToManyReflection, # uses foreign_key RDFPropertyReflection
87
+ ActiveFedora::Reflection::HasManyReflection, # captured by inverse relation
88
+ ActiveFedora::Reflection::HasSubresourceReflection, # ???
89
+ ActiveFedora::Reflection::OrdersReflection # map to :unordered_association in Wings::AttributeTransformer (but retain order)
90
+ next
91
+ when ActiveFedora::Reflection::DirectlyContainsOneReflection
92
+ attribute_name = (reflection_key.to_s.singularize + '_id').to_sym
93
+ type = ::Valkyrie::Types::ID.optional
94
+ when ActiveFedora::Reflection::DirectlyContainsReflection,
95
+ ActiveFedora::Reflection::IndirectlyContainsReflection
96
96
  attribute_name = (reflection_key.to_s.singularize + '_ids').to_sym
97
+ type = ::Valkyrie::Types::Set.of(::Valkyrie::Types::ID)
98
+ when ActiveFedora::Reflection::SingularRDFPropertyReflection
99
+ attribute_name = reflection.name.to_sym
100
+ type = ::Valkyrie::Types::ID.optional
101
+ when ActiveFedora::Reflection::RDFPropertyReflection
102
+ attribute_name = reflection.name.to_sym
103
+ type = ::Valkyrie::Types::Set.of(::Valkyrie::Types::ID)
97
104
  else
98
- type = ::Valkyrie::Types::ID.optional
99
- attribute_name = (reflection_key.to_s.singularize + '_id').to_sym
105
+ raise NotImplementedError, "Expected a known ActiveFedora::Reflection, but got #{reflection}"
100
106
  end
101
107
 
102
- next if fields.include?(attribute_name)
103
- attribute attribute_name, type
108
+ attribute(attribute_name, type)
104
109
  end
105
110
 
106
111
  def internal_resource
data/lib/wings/setup.rb CHANGED
@@ -98,12 +98,12 @@ end
98
98
  Valkyrie::MetadataAdapter.register(
99
99
  Wings::Valkyrie::MetadataAdapter.new, :wings_adapter
100
100
  )
101
- Valkyrie.config.metadata_adapter = :wings_adapter
101
+ Valkyrie.config.metadata_adapter = :wings_adapter unless Hyrax.config.disable_wings
102
102
 
103
103
  Valkyrie::StorageAdapter.register(
104
104
  Wings::Valkyrie::Storage.new, :active_fedora
105
105
  )
106
- Valkyrie.config.storage_adapter = :active_fedora
106
+ Valkyrie.config.storage_adapter = :active_fedora unless Hyrax.config.disable_wings
107
107
 
108
108
  # TODO: Custom query registration is not Wings specific. These custom_queries need to be registered for other adapters too.
109
109
  # A refactor is needed to add the default implementations to hyrax.rb and only handle the wings specific overrides here.
@@ -19,14 +19,9 @@ module Wings
19
19
  # For use with Hyrax, this adapter defaults to Fedora 4.
20
20
  class Storage < ::Valkyrie::Storage::Fedora
21
21
  DEFAULT_CTYPE = 'application/octet-stream'
22
- LINK_HEADER = "<http://www.w3.org/ns/ldp#NonRDFSource>; rel=\"type\""
23
22
  FILES_PATH = 'files'
24
- VERSIONS_SLUG = '/fcr:versions'
25
-
26
- attr_reader :sha1
27
23
 
28
24
  def initialize(connection: Ldp::Client.new(ActiveFedora.fedora.host), base_path: ActiveFedora.fedora.base_path, fedora_version: 4)
29
- @sha1 = fedora_version == 5 ? "sha" : "sha1"
30
25
  super
31
26
  end
32
27
 
@@ -36,84 +31,19 @@ module Wings
36
31
  ::Valkyrie::ID.new(id.to_s.sub(/^.+\/\//, PROTOCOL))
37
32
  end
38
33
 
39
- ##
40
- # @param key [Symbol] the key for plugin behavior to check support for
41
- #
42
- # @return [Boolean] whether
43
- def supports?(key)
44
- key == :versions
45
- end
46
-
47
34
  def upload(file:, original_filename:, resource:, content_type: DEFAULT_CTYPE, # rubocop:disable Metrics/ParameterLists
48
- resource_uri_transformer: default_resource_uri_transformer, use: Hydra::PCDM::Vocab::PCDMTerms.File,
49
- id_hint: 'original', **extra_arguments)
35
+ resource_uri_transformer: default_resource_uri_transformer, use: Hydra::PCDM::Vocab::PCDMTerms.File, # rubocop:disable Lint/UnusedMethodArgument
36
+ id_hint: 'original', **_extra_arguments)
50
37
  id = if resource.try(:file_set?)
51
38
  upload_with_works(resource: resource, file: file, use: use)
52
39
  else
53
- put_file(file: file,
54
- original_filename: original_filename,
55
- resource: resource,
56
- content_type: content_type,
57
- resource_uri_transformer: resource_uri_transformer,
58
- id_hint: id_hint, **extra_arguments)
40
+ return super(file: file, original_filename: original_filename, resource: resource, content_type: content_type, resource_uri_transformer: resource_uri_transformer_factory(id_hint))
59
41
  end
60
-
61
42
  find_by(id: cast_to_valkyrie_id(id))
62
43
  end
63
44
 
64
- ##
65
- # @return [Enumerable<Version> ordered list of versions
66
- def find_versions(id:)
67
- response = connection.http.get(fedora_identifier(id: id) + VERSIONS_SLUG)
68
- return [] if response.status == 404
69
-
70
- reader = RDF::Reader.for(content_type: response.headers['content-type'])
71
- version_graph = RDF::Graph.new << reader.new(response.body)
72
- query = { predicate: RDF::Vocab::Fcrepo4.hasVersion }
73
-
74
- version_graph.query(query).objects.map do |uri|
75
- timestamp =
76
- version_graph.query([uri, RDF::Vocab::Fcrepo4.created, :created])
77
- .first_object
78
- .object
79
- Version.new(id: cast_to_valkyrie_id(uri.to_s), created: timestamp, adapter: self)
80
- end.sort
81
- end
82
-
83
- ##
84
- # abstractly, {Version} objects should have an {#id} and be orderable
85
- # over {#<=>} (allowing e.g. `#sort` to define a consistent order---
86
- # oldest to newest---for a collection of versions). the {#id} should be a
87
- # globally unique identifier for the version.
88
- #
89
- # this implementation uses an orderable {#version_token}. in practice
90
- # the token is the fcrepo created date for the version, as extracted from
91
- # the versions graph.
92
- Version = Struct.new("Version", :id, :created, :adapter, keyword_init: true) do
93
- include Comparable
94
-
95
- ##
96
- # @return [#read]
97
- def io
98
- adapter.find_by(id: id)
99
- end
100
-
101
- def version_token
102
- created
103
- end
104
-
105
- def <=>(other)
106
- raise ArgumentError unless other.respond_to?(:version_token)
107
- version_token <=> other.version_token
108
- end
109
- end
110
-
111
45
  private
112
46
 
113
- def digest_for(file)
114
- "#{sha1}=#{Digest::SHA1.file(file)}"
115
- end
116
-
117
47
  def default_resource_uri_transformer
118
48
  lambda do |resource, hint|
119
49
  id = [CGI.escape(resource.id), FILES_PATH, hint].join('/')
@@ -121,24 +51,12 @@ module Wings
121
51
  end
122
52
  end
123
53
 
124
- ##
125
- # Create a file with HTTP put; no containers here.
126
- # @return [String] the identifier of the created file
127
- def put_file(file:, original_filename:, resource:, content_type:, # rubocop:disable Metrics/ParameterLists
128
- resource_uri_transformer:, id_hint:, **_extra_arguments)
129
- identifier = resource_uri_transformer.call(resource, id_hint)
130
-
131
- connection.http.put do |request|
132
- request.url identifier
133
- request.headers['Content-Type'] = content_type
134
- request.headers['Content-Length'] = (file.try(:size) || file.try(:length)).to_s
135
- request.headers['Content-Disposition'] = "attachment; filename=\"#{original_filename}\""
136
- request.headers['digest'] = digest_for(file)
137
- request.headers['link'] = LINK_HEADER
138
- request.body = Faraday::UploadIO.new(file, content_type, original_filename)
54
+ # Transforms default_resource_uri_transformer to conform to Valkyrie's
55
+ # expected interface of passing a resource and base url.
56
+ def resource_uri_transformer_factory(hint)
57
+ lambda do |resource, _base_url|
58
+ default_resource_uri_transformer.call(resource, hint)
139
59
  end
140
-
141
- identifier
142
60
  end
143
61
 
144
62
  def upload_with_works(resource:, file:, use:)
data/lib/wings.rb CHANGED
@@ -15,6 +15,8 @@
15
15
  # However, these dependencies should be considered temprorary: this code will
16
16
  # be deprecated for removal in a future release.
17
17
  #
18
+ # @deprecated Wings will be removed when ActiveFedora is no longer supported by Hyrax.
19
+ #
18
20
  # @example casting an ActiveFedora model to Valkyrie
19
21
  # work = GenericWork.create(title: ['Comet in Moominland'])
20
22
  # resource = work.valkyrie_resource
@@ -56,6 +58,9 @@
56
58
  # @see https://wiki.duraspace.org/display/samvera/Hyrax-Valkyrie+Development+Working+Group
57
59
  # for further context regarding the approach
58
60
  module Wings
61
+ Deprecation.warn(self, "ActiveFedora and Wings will be removed from a future major release of Hyrax in favor " \
62
+ "of Valkyrie resource models. Please migrate your models from ActiveFedora::Base to Hyrax::Resource.")
63
+
59
64
  ##
60
65
  # @api public
61
66
  #
data/tasks/hyrax_dev.rake CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'English'
3
3
  require 'rspec/core/rake_task'
4
- require 'engine_cart/rake_task'
5
4
  require 'rubocop/rake_task'
6
5
 
7
6
  desc 'Run style checker'
@@ -11,16 +10,6 @@ end
11
10
 
12
11
  RSpec::Core::RakeTask.new(:spec)
13
12
 
14
- desc 'Spin up test servers and run specs'
15
- task :spec_with_app_load do
16
- require 'solr_wrapper' # necessary for rake_support to work
17
- require 'fcrepo_wrapper' # necessary for rake_support to work
18
- require 'active_fedora/rake_support'
19
- with_test_server do
20
- Rake::Task['spec'].invoke
21
- end
22
- end
23
-
24
13
  desc "Sort locales keys in alphabetic order."
25
14
  task :i18n_sorter do
26
15
  require 'i18n_yaml_sorter'
@@ -34,28 +23,8 @@ task :i18n_sorter do
34
23
  end
35
24
  end
36
25
 
37
- if Gem.loaded_specs.key? 'engine_cart'
38
- namespace :engine_cart do
39
- # This generate task should only add its action to an existing engine_cart:generate task
40
- raise 'engine_cart:generate task should already be defined' unless Rake::Task.task_defined?('engine_cart:generate')
41
- task :generate do |_task|
42
- puts 'Running post-generation operations...'
43
- Rake::Task['engine_cart:after_generate'].invoke
44
- end
45
-
46
- desc 'Operations that need to run after the test_app migrations have run'
47
- task :after_generate do
48
- puts 'Creating default collection type...'
49
- EngineCart.within_test_app do
50
- raise "EngineCart failed on with: #{$CHILD_STATUS}" unless
51
- system('bundle exec rake hyrax:default_collection_types:create')
52
- end
53
- end
54
- end
55
- end
56
-
57
- desc 'Generate the engine_cart and spin up test servers and run specs'
58
- task ci: ['rubocop', 'engine_cart:generate'] do
26
+ desc 'Run rubocop and then run specs'
27
+ task ci: ['rubocop'] do
59
28
  puts 'running continuous integration'
60
29
  Rake::Task['spec_with_app_load'].invoke
61
30
  end
data/template.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  # Hack for https://github.com/rails/rails/issues/35153
3
3
  gsub_file 'Gemfile', /^gem ["']sqlite3["']$/, 'gem "sqlite3", "~> 1.3.0"'
4
- gem 'hyrax', '5.0.0.rc1'
4
+ gem 'hyrax', '5.0.0.rc2'
5
5
  run 'bundle install'
6
6
  generate 'hyrax:install', '-f'