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.
- checksums.yaml +4 -4
- data/.dassie/config/initializers/hyrax.rb +11 -1
- data/.gitignore +3 -0
- data/.regen +1 -1
- data/.rubocop_fixme.yml +3 -1
- data/Dockerfile +2 -1
- data/app/actors/hyrax/actors/file_actor.rb +6 -4
- data/app/actors/hyrax/actors/transfer_request_actor.rb +3 -7
- data/app/assets/javascripts/hyrax/analytics_events.js +8 -2
- data/app/assets/javascripts/hyrax/autocomplete/linked_data.es6 +1 -3
- data/app/controllers/concerns/hyrax/controller.rb +21 -0
- data/app/controllers/concerns/hyrax/works_controller_behavior.rb +83 -59
- data/app/controllers/hyrax/admin/admin_sets_controller.rb +105 -19
- data/app/controllers/hyrax/admin/permission_template_accesses_controller.rb +12 -19
- data/app/controllers/hyrax/batch_edits_controller.rb +12 -3
- data/app/controllers/hyrax/batch_uploads_controller.rb +4 -0
- data/app/controllers/hyrax/citations_controller.rb +1 -1
- data/app/controllers/hyrax/dashboard/collections_controller.rb +19 -10
- data/app/forms/hyrax/forms/administrative_set_form.rb +19 -1
- data/app/forms/hyrax/forms/batch_edit_form.rb +1 -1
- data/app/forms/hyrax/forms/dashboard/nest_collection_form.rb +21 -6
- data/app/forms/hyrax/forms/pcdm_collection_form.rb +1 -0
- data/app/forms/hyrax/forms/permission_template_form.rb +17 -9
- data/app/forms/hyrax/forms/resource_form.rb +9 -5
- data/app/helpers/hyrax/collections_helper.rb +14 -0
- data/app/helpers/hyrax/membership_helper.rb +1 -1
- data/app/helpers/hyrax/trophy_helper.rb +1 -1
- data/app/helpers/hyrax/url_helper.rb +1 -1
- data/app/indexers/hyrax/administrative_set_indexer.rb +8 -2
- data/app/indexers/hyrax/deep_indexing_service.rb +1 -1
- data/app/indexers/hyrax/file_set_indexer.rb +1 -0
- data/app/indexers/hyrax/pcdm_collection_indexer.rb +3 -1
- data/app/indexers/hyrax/thumbnail_indexer.rb +31 -0
- data/app/indexers/hyrax/valkyrie_file_set_indexer.rb +6 -6
- data/app/indexers/hyrax/valkyrie_indexer.rb +4 -2
- data/app/indexers/hyrax/valkyrie_work_indexer.rb +13 -0
- data/app/inputs/controlled_vocabulary_input.rb +2 -0
- data/app/jobs/change_depositor_event_job.rb +47 -0
- data/app/jobs/characterize_job.rb +38 -2
- data/app/jobs/concerns/hyrax/members_permission_job_behavior.rb +1 -1
- data/app/jobs/content_depositor_change_event_job.rb +2 -1
- data/app/jobs/hyrax/propagate_change_depositor_job.rb +32 -0
- data/app/jobs/inherit_permissions_job.rb +1 -1
- data/app/jobs/valkyrie_create_derivatives_job.rb +25 -0
- data/app/jobs/valkyrie_ingest_job.rb +84 -16
- data/app/models/admin_set.rb +2 -2
- data/app/models/collection_branding_info.rb +8 -6
- data/app/models/concerns/hyrax/collection_behavior.rb +2 -2
- data/app/models/concerns/hyrax/file_set/characterization.rb +7 -1
- data/app/models/concerns/hyrax/solr_document/metadata.rb +1 -0
- data/app/models/concerns/hyrax/solr_document_behavior.rb +9 -3
- data/app/models/hyrax/administrative_set.rb +36 -1
- data/app/models/hyrax/collection_type.rb +2 -2
- data/app/models/hyrax/file_metadata.rb +5 -1
- data/app/models/hyrax/file_set.rb +42 -1
- data/app/models/hyrax/pcdm_collection.rb +56 -0
- data/app/models/hyrax/permission_template.rb +11 -5
- data/app/models/hyrax/work.rb +91 -0
- data/app/models/proxy_deposit_request.rb +1 -1
- data/app/presenters/hyrax/admin_set_presenter.rb +2 -2
- data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +2 -2
- data/app/presenters/hyrax/work_show_presenter.rb +7 -3
- data/app/search_builders/hyrax/dashboard/collections_search_builder.rb +2 -2
- data/app/search_builders/hyrax/dashboard/managed_search_filters.rb +44 -4
- data/app/search_builders/hyrax/dashboard/nested_collections_search_builder.rb +2 -2
- data/app/search_builders/hyrax/my/collections_search_builder.rb +11 -4
- data/app/services/hyrax/access_control_list.rb +13 -0
- data/app/services/hyrax/admin_set_create_service.rb +21 -37
- data/app/services/hyrax/change_content_depositor_service.rb +2 -2
- data/app/services/hyrax/change_depositor_service.rb +70 -0
- data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +1 -1
- data/app/services/hyrax/collections/nested_collection_query_service.rb +23 -11
- data/app/services/hyrax/custom_queries/navigators/child_file_sets_navigator.rb +45 -0
- data/app/services/hyrax/custom_queries/navigators/child_filesets_navigator.rb +7 -2
- data/app/services/hyrax/custom_queries/navigators/parent_work_navigator.rb +54 -0
- data/app/services/hyrax/default_middleware_stack.rb +3 -0
- data/app/services/hyrax/file_set_derivatives_service.rb +21 -2
- data/app/services/hyrax/file_set_type_service.rb +2 -5
- data/app/services/hyrax/listeners/file_metadata_listener.rb +20 -1
- data/app/services/hyrax/listeners/member_cleanup_listener.rb +23 -3
- data/app/services/hyrax/listeners/metadata_index_listener.rb +39 -0
- data/app/services/hyrax/listeners/proxy_deposit_listener.rb +14 -8
- data/app/services/hyrax/location_service.rb +33 -0
- data/app/services/hyrax/multiple_membership_checker.rb +44 -1
- data/app/services/hyrax/resource_visibility_propagator.rb +1 -1
- data/app/services/hyrax/simple_schema_loader.rb +5 -1
- data/app/services/hyrax/solr_query_service.rb +12 -7
- data/app/services/hyrax/thumbnail_path_service.rb +1 -1
- data/app/services/hyrax/work_uploads_handler.rb +0 -10
- data/app/validators/hyrax/collection_membership_validator.rb +38 -0
- data/app/views/catalog/_index_header_list_hyrax_pcdm_collection.html.erb +4 -0
- data/app/views/hyrax/admin/admin_sets/_form_participant_table.html.erb +2 -2
- data/app/views/hyrax/admin/admin_sets/_form_participants.html.erb +2 -2
- data/app/views/hyrax/admin/admin_sets/_form_visibility.html.erb +2 -2
- data/app/views/hyrax/admin/admin_sets/_form_workflow.erb +1 -1
- data/app/views/hyrax/admin/collection_types/index.html.erb +1 -1
- data/app/views/hyrax/base/_form.html.erb +1 -1
- data/app/views/hyrax/base/_form_child_work_relationships.html.erb +1 -1
- data/app/views/hyrax/dashboard/collections/_default_group.html.erb +2 -2
- data/app/views/hyrax/dashboard/collections/_form.html.erb +21 -15
- data/app/views/hyrax/dashboard/collections/_form_discovery.html.erb +6 -3
- data/app/views/hyrax/dashboard/collections/_form_share.html.erb +2 -2
- data/app/views/hyrax/dashboard/collections/_form_share_table.html.erb +3 -3
- data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +2 -2
- data/app/views/hyrax/dashboard/works/_default_group.html.erb +1 -1
- data/app/views/hyrax/dashboard/works/_list_works.html.erb +1 -1
- data/app/views/hyrax/file_sets/_actions.html.erb +2 -2
- data/app/views/hyrax/my/_work_action_menu.html.erb +8 -9
- data/app/views/hyrax/my/collections/_default_group.html.erb +2 -2
- data/app/views/hyrax/my/collections/_list_collections.html.erb +2 -2
- data/app/views/hyrax/my/collections/index.html.erb +3 -2
- data/app/views/hyrax/my/works/_default_group.html.erb +1 -1
- data/app/views/hyrax/my/works/_list_works.html.erb +1 -2
- data/app/views/hyrax/my/works/index.html.erb +4 -2
- data/chart/hyrax/Chart.yaml +2 -2
- data/chart/hyrax/README.md +22 -1
- data/config/initializers/listeners.rb +0 -1
- data/config/locales/hyrax.de.yml +6 -5
- data/config/locales/hyrax.en.yml +30 -28
- data/config/locales/hyrax.es.yml +10 -9
- data/config/locales/hyrax.fr.yml +2 -1
- data/config/locales/hyrax.it.yml +3 -2
- data/config/locales/hyrax.pt-BR.yml +2 -1
- data/config/locales/hyrax.zh.yml +2 -1
- data/config/metadata/basic_metadata.yaml +2 -0
- data/config/metadata/core_metadata.yaml +1 -1
- data/docker-compose.yml +46 -42
- data/documentation/developing-your-hyrax-based-app.md +1 -1
- data/documentation/legacyREADME.md +1 -1
- data/lib/hyrax/administrative_set_name.rb +18 -0
- data/lib/hyrax/collection_name.rb +2 -0
- data/lib/hyrax/configuration.rb +10 -0
- data/lib/hyrax/controlled_vocabularies/location.rb +9 -2
- data/lib/hyrax/controlled_vocabularies/resource_label_caching.rb +42 -0
- data/lib/hyrax/controlled_vocabularies.rb +1 -0
- data/lib/hyrax/publisher.rb +45 -0
- data/lib/hyrax/specs/capybara.rb +1 -1
- data/lib/hyrax/specs/shared_specs/hydra_works.rb +11 -4
- data/lib/hyrax/specs/shared_specs/indexers.rb +117 -3
- data/lib/hyrax/transactions/admin_set_create.rb +2 -1
- data/lib/hyrax/transactions/admin_set_destroy.rb +22 -0
- data/lib/hyrax/transactions/admin_set_update.rb +21 -0
- data/lib/hyrax/transactions/collection_destroy.rb +22 -0
- data/lib/hyrax/transactions/collection_update.rb +3 -2
- data/lib/hyrax/transactions/container.rb +87 -23
- data/lib/hyrax/transactions/create_work.rb +3 -0
- data/lib/hyrax/transactions/destroy_work.rb +3 -0
- data/lib/hyrax/transactions/steps/apply_collection_permission_template.rb +2 -0
- data/lib/hyrax/transactions/steps/apply_permission_template.rb +2 -0
- data/lib/hyrax/transactions/steps/apply_visibility.rb +2 -0
- data/lib/hyrax/transactions/steps/change_depositor.rb +46 -0
- data/lib/hyrax/transactions/steps/check_for_empty_admin_set.rb +36 -0
- data/lib/hyrax/transactions/steps/delete_access_control.rb +32 -0
- data/lib/hyrax/transactions/steps/delete_resource.rb +19 -3
- data/lib/hyrax/transactions/steps/destroy_work.rb +3 -1
- data/lib/hyrax/transactions/steps/ensure_permission_template.rb +2 -0
- data/lib/hyrax/transactions/steps/save.rb +24 -6
- data/lib/hyrax/transactions/steps/save_access_control.rb +2 -2
- data/lib/hyrax/transactions/steps/save_work.rb +3 -0
- data/lib/hyrax/transactions/steps/set_user_as_creator.rb +41 -0
- data/lib/hyrax/transactions/steps/update_work_members.rb +51 -0
- data/lib/hyrax/transactions/update_work.rb +4 -3
- data/lib/hyrax/transactions/work_create.rb +1 -1
- data/lib/hyrax/transactions/work_destroy.rb +2 -1
- data/lib/hyrax/transactions/work_update.rb +19 -0
- data/lib/hyrax/version.rb +1 -1
- data/lib/wings/attribute_transformer.rb +5 -1
- data/lib/wings/setup.rb +3 -1
- data/lib/wings/valkyrie/query_service.rb +2 -1
- data/lib/wings/valkyrie/storage.rb +7 -1
- data/template.rb +1 -1
- metadata +24 -3
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Log work depositor change to activity streams
|
|
3
|
+
#
|
|
4
|
+
# This class simply logs the transfer, pulling data from the object that was
|
|
5
|
+
# just transferred. It does not perform the transfer.
|
|
6
|
+
class ChangeDepositorEventJob < ContentEventJob
|
|
7
|
+
include Rails.application.routes.url_helpers
|
|
8
|
+
include ActionDispatch::Routing::PolymorphicRoutes
|
|
9
|
+
|
|
10
|
+
# @param [ActiveFedora::Base, Hyrax::Work] work the work that's been transfered
|
|
11
|
+
def perform(work)
|
|
12
|
+
# these get set to repo_object and depositor
|
|
13
|
+
super(work, new_owner(work))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def action
|
|
17
|
+
"User #{link_to_profile repo_object.proxy_depositor} has transferred #{link_to_work repo_object.title.first} to user #{link_to_profile depositor}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def link_to_work(text)
|
|
21
|
+
link_to text, polymorphic_path(repo_object)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Log the event to the work's stream
|
|
25
|
+
def log_work_event(work)
|
|
26
|
+
work.log_event(event)
|
|
27
|
+
end
|
|
28
|
+
alias log_file_set_event log_work_event
|
|
29
|
+
|
|
30
|
+
# overriding default to log the event to the depositor instead of their profile
|
|
31
|
+
# and to log the event for both users
|
|
32
|
+
def log_user_event(depositor)
|
|
33
|
+
previous_owner.log_profile_event(event)
|
|
34
|
+
depositor.log_event(event)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def previous_owner
|
|
40
|
+
::User.find_by_user_key(repo_object.proxy_depositor)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# used for @depositor
|
|
44
|
+
def new_owner(work)
|
|
45
|
+
::User.find_by_user_key(work.depositor)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -36,12 +36,48 @@ class CharacterizeJob < Hyrax::ApplicationJob
|
|
|
36
36
|
|
|
37
37
|
private
|
|
38
38
|
|
|
39
|
-
def characterize(file_set, _file_id, filepath)
|
|
39
|
+
def characterize(file_set, _file_id, filepath) # rubocop:disable Metrics/AbcSize
|
|
40
|
+
# store this so we can tell if the original_file is actually changing
|
|
41
|
+
previous_checksum = file_set.characterization_proxy.original_checksum.first
|
|
42
|
+
|
|
43
|
+
clear_metadata(file_set)
|
|
44
|
+
|
|
45
|
+
# If the current FileSet title is the same as the label, it must be a filename as opposed to a user-entered...
|
|
46
|
+
# value. So later we'll ensure it's set to the new file's filename.
|
|
47
|
+
reset_title = file_set.title.first == file_set.label
|
|
48
|
+
|
|
40
49
|
characterization_service.run(file_set.characterization_proxy, filepath)
|
|
41
50
|
Rails.logger.debug "Ran characterization on #{file_set.characterization_proxy.id} (#{file_set.characterization_proxy.mime_type})"
|
|
42
51
|
file_set.characterization_proxy.alpha_channels = channels(filepath) if file_set.image? && Hyrax.config.iiif_image_server?
|
|
43
52
|
file_set.characterization_proxy.save!
|
|
44
|
-
|
|
53
|
+
|
|
54
|
+
# Ensure that if the actual file content has changed, the mod timestamp on the FileSet object changes.
|
|
55
|
+
# Otherwise this does not happen when rolling back to a previous version. Perhaps this should be set as part of...
|
|
56
|
+
# `FileActor.revert_to` (or its replacement Transaction?!), where the FileSet is saved. Not sure if the...
|
|
57
|
+
# before/after checksum is readily available there though. I like this checksum verification because it allows...
|
|
58
|
+
# all changes to the current FileSet version to be detected, which in our case triggers re-creation of a...
|
|
59
|
+
# "cold storage" archive of the parent Work. It's worth noting that adding a *new* version always touches this...
|
|
60
|
+
# mod time. This is done in the versioning code.
|
|
61
|
+
file_set.date_modified = Hyrax::TimeService.time_in_utc if file_set.characterization_proxy.original_checksum.first != previous_checksum
|
|
62
|
+
|
|
63
|
+
# set title to label if that's how it was before this characterization
|
|
64
|
+
file_set.title = [file_set.characterization_proxy.original_name] if reset_title
|
|
65
|
+
# always set the label to the original_name
|
|
66
|
+
file_set.label = file_set.characterization_proxy.original_name
|
|
67
|
+
|
|
68
|
+
file_set.save!
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def clear_metadata(file_set)
|
|
72
|
+
# The characterization of additional file versions adds new height/width/size/checksum values to un-orderable...
|
|
73
|
+
# `ActiveTriples::Relation` fields on `original_file`. Values from those are then randomly pulled into Solr...
|
|
74
|
+
# fields which may have scalar or vector cardinality. So for height/width you get two scalar values pulled from...
|
|
75
|
+
# "randomized parallel arrays". Upshot is to reset all of these before (re)characterization to stop the mayhem.
|
|
76
|
+
file_set.characterization_proxy.height = []
|
|
77
|
+
file_set.characterization_proxy.width = []
|
|
78
|
+
file_set.characterization_proxy.original_checksum = []
|
|
79
|
+
file_set.characterization_proxy.file_size = []
|
|
80
|
+
file_set.characterization_proxy.format_label = []
|
|
45
81
|
end
|
|
46
82
|
|
|
47
83
|
def channels(filepath)
|
|
@@ -17,7 +17,7 @@ module Hyrax
|
|
|
17
17
|
when ActiveFedora::Base
|
|
18
18
|
::FileSet.search_with_conditions(id: work.member_ids).map(&:id)
|
|
19
19
|
when Valkyrie::Resource
|
|
20
|
-
Hyrax.custom_queries.
|
|
20
|
+
Hyrax.custom_queries.find_child_file_set_ids(resource: work)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -8,10 +8,11 @@ class ContentDepositorChangeEventJob < ContentEventJob
|
|
|
8
8
|
|
|
9
9
|
attr_accessor :reset
|
|
10
10
|
|
|
11
|
-
# @param [ActiveFedora::Base] work the work to be
|
|
11
|
+
# @param [ActiveFedora::Base, Hyrax::Work] work the work to be transferred
|
|
12
12
|
# @param [User] user the user the work is being transfered to.
|
|
13
13
|
# @param [TrueClass,FalseClass] reset (false) if true, reset the access controls. This revokes edit access from the depositor
|
|
14
14
|
def perform(work, user, reset = false)
|
|
15
|
+
Deprecation.warn("This class will be removed in the next major release. Use Hyrax::ChangeDepositorService.call instead.")
|
|
15
16
|
@reset = reset
|
|
16
17
|
super(work, user)
|
|
17
18
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Hyrax
|
|
3
|
+
# updates depositor on file sets and resets permissions if flagged. Used by
|
|
4
|
+
# ChangeDepositorService to background changes to lots of file sets
|
|
5
|
+
class PropagateChangeDepositorJob < ApplicationJob
|
|
6
|
+
# @param work_id [Valkyrie::Id, String] the id of the work
|
|
7
|
+
# that is receiving a change of depositor
|
|
8
|
+
# @param user [User] the user that will "become" the depositor of
|
|
9
|
+
# the given work
|
|
10
|
+
# @param reset [TrueClass, FalseClass] when true, first clear
|
|
11
|
+
# permissions for the given work and contained file
|
|
12
|
+
# sets; regardless of true/false make the given user
|
|
13
|
+
# the depositor of the given work
|
|
14
|
+
def perform(work_id, user, reset)
|
|
15
|
+
work = Hyrax.query_service.find_by(id: work_id)
|
|
16
|
+
Hyrax.custom_queries.find_child_file_sets(resource: work).each do |f|
|
|
17
|
+
if reset
|
|
18
|
+
f.permission_manager.acl.permissions = []
|
|
19
|
+
f.permission_manager.acl.save
|
|
20
|
+
end
|
|
21
|
+
apply_depositor_metadata(f, user)
|
|
22
|
+
Hyrax.persister.save(resource: f)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def apply_depositor_metadata(resource, depositor)
|
|
27
|
+
depositor_id = depositor.respond_to?(:user_key) ? depositor.user_key : depositor
|
|
28
|
+
resource.depositor = depositor_id if resource.respond_to? :depositor=
|
|
29
|
+
Hyrax::AccessControlList.new(resource: resource).grant(:edit).to(::User.find_by_user_key(depositor_id)).save
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -24,7 +24,7 @@ class InheritPermissionsJob < Hyrax::ApplicationJob
|
|
|
24
24
|
# @param work [Resource]
|
|
25
25
|
# @return [Array<Hyrax::File_Set>]
|
|
26
26
|
def file_sets_for(work)
|
|
27
|
-
Hyrax.custom_queries.
|
|
27
|
+
Hyrax.custom_queries.find_child_file_sets(resource: work)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Perform the copy from the work to the contained filesets
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
class ValkyrieCreateDerivativesJob < Hyrax::ApplicationJob
|
|
3
|
+
queue_as Hyrax.config.ingest_queue_name
|
|
4
|
+
def perform(_file_set_id, file_id, _filepath = nil)
|
|
5
|
+
file_metadata = Hyrax.custom_queries.find_file_metadata_by(id: file_id)
|
|
6
|
+
return if file_metadata.video? && !Hyrax.config.enable_ffmpeg
|
|
7
|
+
# Get file into a local path.
|
|
8
|
+
file = Hyrax.storage_adapter.find_by(id: file_metadata.file_identifier)
|
|
9
|
+
# Call derivatives with the file_set.
|
|
10
|
+
derivative_service = Hyrax::DerivativeService.for(file_metadata)
|
|
11
|
+
derivative_service.create_derivatives(file.disk_path)
|
|
12
|
+
# Trigger a reindex to get the thumbnail path.
|
|
13
|
+
Hyrax.publisher.publish('file.metadata.updated', metadata: file_metadata, user: nil)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def query_service
|
|
19
|
+
Hyrax.query_service
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def storage_adapter
|
|
23
|
+
Hyrax.storage_adapter
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -1,56 +1,124 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
# Ingests a {Hyrax::UploadedFile} as file member of a {Hyrax::FileSet}.
|
|
5
|
+
#
|
|
6
|
+
# The {Hyrax::UploadedFile} is passed into {#perform}, and should have a
|
|
7
|
+
# {Hyrax::UploadedFile#file_set_uri} identifying an existing {Hyrax::FileSet}.
|
|
2
8
|
class ValkyrieIngestJob < Hyrax::ApplicationJob
|
|
3
9
|
queue_as Hyrax.config.ingest_queue_name
|
|
4
10
|
|
|
5
11
|
##
|
|
6
|
-
# @param [
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
# @param [Hyrax::UploadedFile] file
|
|
13
|
+
# @param [RDF::URI] pcdm_use is the use/type to apply to the created FileMetadata
|
|
14
|
+
# @see Hyrax::FileMetadata::Use
|
|
15
|
+
def perform(file, pcdm_use: Hyrax::FileMetadata::Use::ORIGINAL_FILE)
|
|
16
|
+
ingest(file: file, pcdm_use: pcdm_use)
|
|
9
17
|
end
|
|
10
18
|
|
|
11
19
|
##
|
|
12
|
-
# @
|
|
20
|
+
# @api private
|
|
13
21
|
#
|
|
22
|
+
# @param [Hyrax::UploadedFile] file
|
|
23
|
+
# @param [RDF::URI] pcdm_use
|
|
24
|
+
|
|
14
25
|
# @return [void]
|
|
15
|
-
def ingest(file:)
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
def ingest(file:, pcdm_use:)
|
|
27
|
+
file_set_uri = Valkyrie::ID.new(file.file_set_uri)
|
|
28
|
+
file_set = Hyrax.query_service.find_by(id: file_set_uri)
|
|
29
|
+
|
|
30
|
+
updated_metadata = upload_file(file: file, file_set: file_set, pcdm_use: pcdm_use)
|
|
18
31
|
|
|
19
|
-
add_file_to_file_set(file_set: file_set,
|
|
32
|
+
add_file_to_file_set(file_set: file_set,
|
|
33
|
+
file_metadata: updated_metadata,
|
|
34
|
+
user: file.user)
|
|
35
|
+
|
|
36
|
+
ValkyrieCreateDerivativesJob.perform_later(file_set.id.to_s, updated_metadata.id.to_s)
|
|
20
37
|
end
|
|
21
38
|
|
|
22
39
|
##
|
|
23
|
-
# @
|
|
24
|
-
#
|
|
40
|
+
# @api private
|
|
41
|
+
#
|
|
25
42
|
# @param [Hyrax::FileSet] file_set the file set to add to
|
|
26
43
|
# @param [Hyrax::FileMetadata] file_metadata the metadata object representing
|
|
27
44
|
# the file to add
|
|
45
|
+
# @param [::User] user the user performing the add
|
|
28
46
|
#
|
|
29
47
|
# @return [Hyrax::FileSet] updated file set
|
|
30
|
-
def add_file_to_file_set(file_set:, file_metadata:)
|
|
48
|
+
def add_file_to_file_set(file_set:, file_metadata:, user:)
|
|
31
49
|
file_set.file_ids << file_metadata.id
|
|
50
|
+
set_file_use_ids(file_set, file_metadata)
|
|
51
|
+
|
|
32
52
|
Hyrax.persister.save(resource: file_set)
|
|
53
|
+
Hyrax.publisher.publish('object.membership.updated', object: file_set, user: user)
|
|
33
54
|
end
|
|
34
55
|
|
|
35
56
|
##
|
|
57
|
+
# @api private
|
|
58
|
+
#
|
|
36
59
|
# @param [Hyrax::UploadedFile] file
|
|
37
60
|
# @param [Hyrax::FileSet] file_set
|
|
61
|
+
# @param [RDF::URI] pcdm_use the use/type to apply to the created FileMetadata
|
|
38
62
|
#
|
|
39
63
|
# @return [Hyrax::FileMetadata] the metadata representing the uploaded file
|
|
40
|
-
def upload_file(file:, file_set:)
|
|
64
|
+
def upload_file(file:, file_set:, pcdm_use:) # rubocop:disable Metrics/MethodLength
|
|
41
65
|
carrier_wave_sanitized_file = file.uploader.file
|
|
66
|
+
# Pull file, since carrierwave files don't respond to a proper IO #read. See
|
|
67
|
+
# https://github.com/carrierwaveuploader/carrierwave/issues/1959
|
|
68
|
+
file_io = carrier_wave_sanitized_file.to_file
|
|
42
69
|
uploaded = Hyrax.storage_adapter
|
|
43
70
|
.upload(resource: file_set,
|
|
44
|
-
file:
|
|
71
|
+
file: file_io,
|
|
45
72
|
original_filename: carrier_wave_sanitized_file.original_filename)
|
|
46
73
|
|
|
47
|
-
file_metadata =
|
|
74
|
+
file_metadata = find_or_create_metadata(id: uploaded.id, file: carrier_wave_sanitized_file)
|
|
75
|
+
|
|
76
|
+
file_metadata.type << pcdm_use
|
|
48
77
|
file_metadata.file_set_id = file.file_set_uri
|
|
49
78
|
file_metadata.file_identifier = uploaded.id
|
|
50
79
|
file_metadata.size = uploaded.size
|
|
51
80
|
|
|
52
|
-
Hyrax.
|
|
81
|
+
saved_metadata = Hyrax.persister.save(resource: file_metadata)
|
|
82
|
+
Hyrax.publisher.publish("object.file.uploaded", metadata: saved_metadata)
|
|
83
|
+
file_io.close
|
|
84
|
+
|
|
85
|
+
if pcdm_use == Hyrax::FileMetadata::Use::ORIGINAL_FILE
|
|
86
|
+
# Set file set label.
|
|
87
|
+
reset_title = file_set.title.first == file_set.label
|
|
88
|
+
# set title to label if that's how it was before this characterization
|
|
89
|
+
file_set.title = file_metadata.original_filename if reset_title
|
|
90
|
+
# always set the label to the original_name
|
|
91
|
+
file_set.label = file_metadata.original_filename
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
saved_metadata
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
##
|
|
98
|
+
# @api private
|
|
99
|
+
def find_or_create_metadata(id:, file:)
|
|
100
|
+
Hyrax.custom_queries.find_file_metadata_by(id: id)
|
|
101
|
+
rescue Valkyrie::Persistence::ObjectNotFoundError => e
|
|
102
|
+
Hyrax.logger.warn "Failed to find existing metadata for #{id}:"
|
|
103
|
+
Hyrax.logger.warn e.message
|
|
104
|
+
Hyrax.logger.warn "Creating Hyrax::FileMetadata now"
|
|
105
|
+
Hyrax::FileMetadata.for(file: file)
|
|
106
|
+
end
|
|
53
107
|
|
|
54
|
-
|
|
108
|
+
##
|
|
109
|
+
# @api private
|
|
110
|
+
def set_file_use_ids(file_set, file_metadata)
|
|
111
|
+
file_metadata.type.each do |type|
|
|
112
|
+
case type
|
|
113
|
+
when Hyrax::FileMetadata::Use::ORIGINAL_FILE
|
|
114
|
+
file_set.original_file_id = file_metadata.id
|
|
115
|
+
when Hyrax::FileMetadata::Use::THUMBNAIL
|
|
116
|
+
file_set.thumbnail_id = file_metadata.id
|
|
117
|
+
when Hyrax::FileMetadata::Use::EXTRACTED_TEXT
|
|
118
|
+
file_set.extracted_text_id = file_metadata.id
|
|
119
|
+
else
|
|
120
|
+
Rails.logger.warn "Unknown file use #{file_metadata.type} specified for #{file_metadata.file_identifier}"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
55
123
|
end
|
|
56
124
|
end
|
data/app/models/admin_set.rb
CHANGED
|
@@ -87,12 +87,12 @@ class AdminSet < ActiveFedora::Base
|
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
##
|
|
90
|
-
# @deprecated use PermissionTemplate#
|
|
90
|
+
# @deprecated use PermissionTemplate#reset_access_controls_for instead
|
|
91
91
|
#
|
|
92
92
|
# Calculate and update who should have edit access based on who
|
|
93
93
|
# has "manage" access in the PermissionTemplateAccess
|
|
94
94
|
def reset_access_controls!
|
|
95
|
-
Deprecation.warn("reset_access_controls! is deprecated; use PermissionTemplate#
|
|
95
|
+
Deprecation.warn("reset_access_controls! is deprecated; use PermissionTemplate#reset_access_controls_for instead.")
|
|
96
96
|
|
|
97
97
|
permission_template.reset_access_controls_for(collection: self)
|
|
98
98
|
end
|
|
@@ -14,16 +14,19 @@ class CollectionBrandingInfo < ApplicationRecord
|
|
|
14
14
|
self.local_path = File.join(role, filename)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def save(file_location,
|
|
17
|
+
def save(file_location, upload_file = true)
|
|
18
18
|
filename = File.split(local_path).last
|
|
19
19
|
role_and_filename = File.join(role, filename)
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
if upload_file
|
|
22
|
+
storage.upload(resource: Hyrax::PcdmCollection.new(id: collection_id),
|
|
23
|
+
file: File.open(file_location),
|
|
24
|
+
original_filename: role_and_filename)
|
|
25
|
+
end
|
|
26
|
+
|
|
24
27
|
self.local_path = find_local_filename(collection_id, role, filename)
|
|
25
28
|
|
|
26
|
-
FileUtils.remove_file(file_location) if File.exist?(file_location) &&
|
|
29
|
+
FileUtils.remove_file(file_location) if File.exist?(file_location) && upload_file
|
|
27
30
|
super()
|
|
28
31
|
end
|
|
29
32
|
|
|
@@ -35,7 +38,6 @@ class CollectionBrandingInfo < ApplicationRecord
|
|
|
35
38
|
else
|
|
36
39
|
local_path
|
|
37
40
|
end
|
|
38
|
-
|
|
39
41
|
storage.delete(id: id)
|
|
40
42
|
end
|
|
41
43
|
|
|
@@ -121,12 +121,12 @@ module Hyrax
|
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
##
|
|
124
|
-
# @deprecated use PermissionTemplate#
|
|
124
|
+
# @deprecated use PermissionTemplate#reset_access_controls_for instead
|
|
125
125
|
#
|
|
126
126
|
# Calculate and update who should have read/edit access to the collections based on who
|
|
127
127
|
# has access in PermissionTemplateAccess
|
|
128
128
|
def reset_access_controls!
|
|
129
|
-
Deprecation.warn("reset_access_controls! is deprecated; use PermissionTemplate#
|
|
129
|
+
Deprecation.warn("reset_access_controls! is deprecated; use PermissionTemplate#reset_access_controls_for instead.")
|
|
130
130
|
|
|
131
131
|
permission_template
|
|
132
132
|
.reset_access_controls_for(collection: self, interpret_visibility: true)
|
|
@@ -29,7 +29,7 @@ module Hyrax
|
|
|
29
29
|
:page_count, :file_title, :last_modified, :original_checksum,
|
|
30
30
|
:duration, :sample_rate, :alpha_channels
|
|
31
31
|
]
|
|
32
|
-
self.characterization_proxy =
|
|
32
|
+
self.characterization_proxy = Hyrax.config.characterization_proxy
|
|
33
33
|
|
|
34
34
|
delegate(*characterization_terms, to: :characterization_proxy)
|
|
35
35
|
|
|
@@ -64,6 +64,12 @@ module Hyrax
|
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas << AlphaChannelsSchema
|
|
67
|
+
|
|
68
|
+
# Add file_set_id for Valkyrie support.
|
|
69
|
+
class FileSetIdSchema < ActiveTriples::Schema
|
|
70
|
+
property :file_set_id, predicate: ::RDF::URI.new('http://vocabulary.samvera.org/ns#fileSetId')
|
|
71
|
+
end
|
|
72
|
+
ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas << FileSetIdSchema
|
|
67
73
|
end
|
|
68
74
|
end
|
|
69
75
|
end
|
|
@@ -52,6 +52,7 @@ module Hyrax
|
|
|
52
52
|
attribute :read_groups, Solr::Array, ::Ability.read_group_field
|
|
53
53
|
attribute :collection_ids, Solr::Array, 'collection_ids_tesim'
|
|
54
54
|
attribute :admin_set, Solr::Array, "admin_set_tesim"
|
|
55
|
+
attribute :admin_set_id, Solr::Array, "admin_set_id_ssim"
|
|
55
56
|
attribute :member_ids, Solr::Array, "member_ids_ssim"
|
|
56
57
|
attribute :member_of_collection_ids, Solr::Array, "member_of_collection_ids_ssim"
|
|
57
58
|
attribute :member_of_collections, Solr::Array, "member_of_collections_ssim"
|
|
@@ -65,7 +65,7 @@ module Hyrax
|
|
|
65
65
|
##
|
|
66
66
|
# @return [Boolean]
|
|
67
67
|
def admin_set?
|
|
68
|
-
hydra_model ==
|
|
68
|
+
hydra_model == Hyrax.config.admin_set_class
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
##
|
|
@@ -75,9 +75,9 @@ module Hyrax
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
# Method to return the model
|
|
78
|
-
def hydra_model(classifier:
|
|
78
|
+
def hydra_model(classifier: nil)
|
|
79
79
|
first('has_model_ssim')&.safe_constantize ||
|
|
80
|
-
classifier.classifier(self).best_model
|
|
80
|
+
model_classifier(classifier).classifier(self).best_model
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
def depositor(default = '')
|
|
@@ -107,5 +107,11 @@ module Hyrax
|
|
|
107
107
|
def collection_type_gid
|
|
108
108
|
first(Hyrax.config.collection_type_index_field)
|
|
109
109
|
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def model_classifier(classifier)
|
|
114
|
+
classifier || ActiveFedora.model_mapper
|
|
115
|
+
end
|
|
110
116
|
end
|
|
111
117
|
end
|
|
@@ -1,18 +1,53 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_dependency 'hyrax/administrative_set_name'
|
|
4
|
+
|
|
3
5
|
module Hyrax
|
|
4
6
|
##
|
|
5
7
|
# Valkyrie model for Admin Set domain objects.
|
|
8
|
+
#
|
|
9
|
+
# ## Relationships
|
|
10
|
+
#
|
|
11
|
+
# ### Administrative Set and Work
|
|
12
|
+
#
|
|
13
|
+
# * Defined: The relationship is defined by the inverse relationship stored in the
|
|
14
|
+
# work's `:admin_set_id` attribute.
|
|
15
|
+
# * Tested: The work tests the relationship.
|
|
16
|
+
# * Administrative Set to Work: (1..m) An admin set can have many works.
|
|
17
|
+
#
|
|
18
|
+
# @example Get works in an admin set:
|
|
19
|
+
# works = Hyrax.query_service.find_inverse_references_by(id: admin_set.id, property: :admin_set_id)
|
|
20
|
+
#
|
|
21
|
+
# * Work to Administrative Set: (1..1) A work must be in one and only one admin set.
|
|
22
|
+
# * See Hyrax::Work for code to get and set the admin set for the work.
|
|
23
|
+
#
|
|
24
|
+
# @see Hyrax::Work
|
|
25
|
+
# @see Valkyrie query adapter's #find_inverse_references_by
|
|
26
|
+
#
|
|
6
27
|
class AdministrativeSet < Hyrax::Resource
|
|
7
28
|
include Hyrax::Schema(:core_metadata)
|
|
8
29
|
|
|
9
30
|
attribute :alternative_title, Valkyrie::Types::Set.of(Valkyrie::Types::String)
|
|
10
31
|
attribute :creator, Valkyrie::Types::Set.of(Valkyrie::Types::String)
|
|
11
|
-
attribute :description, Valkyrie::Types::
|
|
32
|
+
attribute :description, Valkyrie::Types::String
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# @return [Boolean] true
|
|
36
|
+
def collection?
|
|
37
|
+
true
|
|
38
|
+
end
|
|
12
39
|
|
|
13
40
|
def collection_type_gid
|
|
14
41
|
# allow AdministrativeSet to behave more like a regular PcdmCollection
|
|
15
42
|
Hyrax::CollectionType.find_or_create_admin_set_type.to_global_id
|
|
16
43
|
end
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# @api private
|
|
47
|
+
#
|
|
48
|
+
# @return [Class] an ActiveModel::Name compatible class
|
|
49
|
+
def self._hyrax_default_name_class
|
|
50
|
+
Hyrax::AdministrativeSetName
|
|
51
|
+
end
|
|
17
52
|
end
|
|
18
53
|
end
|
|
@@ -109,9 +109,9 @@ module Hyrax
|
|
|
109
109
|
|
|
110
110
|
##
|
|
111
111
|
# @return [Enumerable<Collection, PcdmCollection>]
|
|
112
|
-
def collections(use_valkyrie:
|
|
112
|
+
def collections(use_valkyrie: Hyrax.config.use_valkyrie?)
|
|
113
113
|
return [] unless id
|
|
114
|
-
return Hyrax.custom_queries.find_collections_by_type(global_id: to_global_id) if use_valkyrie
|
|
114
|
+
return Hyrax.custom_queries.find_collections_by_type(global_id: to_global_id.to_s) if use_valkyrie
|
|
115
115
|
ActiveFedora::Base.where(Hyrax.config.collection_type_index_field.to_sym => to_global_id.to_s)
|
|
116
116
|
end
|
|
117
117
|
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
module Hyrax
|
|
4
4
|
class FileMetadata < Valkyrie::Resource
|
|
5
|
+
# Include mime-types for Hydra Derivatives mime-type checking. We may want
|
|
6
|
+
# to move this logic someday.
|
|
7
|
+
include Hydra::Works::MimeTypes
|
|
8
|
+
|
|
5
9
|
GENERIC_MIME_TYPE = 'application/octet-stream'
|
|
6
10
|
|
|
7
11
|
##
|
|
@@ -42,7 +46,7 @@ module Hyrax
|
|
|
42
46
|
attribute :label, ::Valkyrie::Types::Set
|
|
43
47
|
attribute :original_filename, ::Valkyrie::Types::String
|
|
44
48
|
attribute :mime_type, ::Valkyrie::Types::String.default(GENERIC_MIME_TYPE)
|
|
45
|
-
attribute :type, ::Valkyrie::Types::Set.default([Use::ORIGINAL_FILE]
|
|
49
|
+
attribute :type, ::Valkyrie::Types::Set.default([Use::ORIGINAL_FILE])
|
|
46
50
|
|
|
47
51
|
# attributes set by fits
|
|
48
52
|
attribute :format_label, ::Valkyrie::Types::Set
|
|
@@ -4,6 +4,30 @@ module Hyrax
|
|
|
4
4
|
##
|
|
5
5
|
# Valkyrie model for `FileSet` domain objects in the Hydra Works model.
|
|
6
6
|
#
|
|
7
|
+
# ## Relationships
|
|
8
|
+
#
|
|
9
|
+
# ### File Set and Work
|
|
10
|
+
#
|
|
11
|
+
# * Defined: The relationship is defined by the inverse relationship stored in the
|
|
12
|
+
# work's `:member_ids` attribute.
|
|
13
|
+
# * Tested: The work tests the relationship.
|
|
14
|
+
# * File Set to Work: (1..1) A file set must be in one and only one work.
|
|
15
|
+
#
|
|
16
|
+
# @example Get work for a file set:
|
|
17
|
+
# work = Hyrax.custom_queries.find_parent_work(resource: file_set)
|
|
18
|
+
#
|
|
19
|
+
# * Work to File Set: (0..m) A work can have many file sets.
|
|
20
|
+
# * See Hyrax::Work for code to get and set file sets for the work.
|
|
21
|
+
#
|
|
22
|
+
# ### File Set and File (TBD)
|
|
23
|
+
#
|
|
24
|
+
# @see Hyrax::Work
|
|
25
|
+
# @see Hyrax::CustomQueries::Navigators::ParentWorkNavigator#find_parent_work
|
|
26
|
+
#
|
|
27
|
+
# @todo The description in Hydra::Works Shared Modeling is out of date and uses
|
|
28
|
+
# terminology to describe the relationships that is no longer used in code.
|
|
29
|
+
# Update the model and link to it. This can be a simple relationship diagram
|
|
30
|
+
# with a link to the original Works Shared Modeling for historical perspective.
|
|
7
31
|
# @see https://wiki.duraspace.org/display/samvera/Hydra%3A%3AWorks+Shared+Modeling
|
|
8
32
|
class FileSet < Hyrax::Resource
|
|
9
33
|
include Hyrax::Schema(:core_metadata)
|
|
@@ -15,11 +39,28 @@ module Hyrax
|
|
|
15
39
|
end
|
|
16
40
|
end
|
|
17
41
|
|
|
42
|
+
class_attribute :characterization_proxy
|
|
43
|
+
self.characterization_proxy = Hyrax.config.characterization_proxy
|
|
44
|
+
|
|
18
45
|
attribute :file_ids, Valkyrie::Types::Array.of(Valkyrie::Types::ID) # id for FileMetadata resources
|
|
46
|
+
attribute :thumbnail_id, Valkyrie::Types::ID.optional # id for FileMetadata resource
|
|
19
47
|
attribute :original_file_id, Valkyrie::Types::ID # id for FileMetadata resource
|
|
20
|
-
attribute :thumbnail_id, Valkyrie::Types::ID # id for FileMetadata resource
|
|
21
48
|
attribute :extracted_text_id, Valkyrie::Types::ID # id for FileMetadata resource
|
|
22
49
|
|
|
50
|
+
##
|
|
51
|
+
# @return [Valkyrie::ID]
|
|
52
|
+
def representative_id
|
|
53
|
+
id
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# @return [Valkyrie::ID]
|
|
58
|
+
# If one is set then return it, otherwise use self as the ID to allow for
|
|
59
|
+
# derivative generators to find the on-disk path for the thumbnail.
|
|
60
|
+
def thumbnail_id
|
|
61
|
+
self.[](:thumbnail_id) || id
|
|
62
|
+
end
|
|
63
|
+
|
|
23
64
|
##
|
|
24
65
|
# @return [Boolean] true
|
|
25
66
|
def pcdm_object?
|