bulk_ops 0.1.3

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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/app/assets/images/bulk_ops/github_logo.png +0 -0
  3. data/app/assets/javascripts/bulk_ops.js +14 -0
  4. data/app/assets/javascripts/bulk_ops/selections.js +24 -0
  5. data/app/assets/javascripts/selections.js +38 -0
  6. data/app/assets/javascripts/work_search.js +64 -0
  7. data/app/assets/stylesheets/bulk_ops.scss +99 -0
  8. data/app/controllers/bulk_ops/application_controller.rb +13 -0
  9. data/app/controllers/bulk_ops/github_authorization_controller.rb +33 -0
  10. data/app/controllers/bulk_ops/operations_controller.rb +481 -0
  11. data/app/jobs/bulk_ops/application_job.rb +4 -0
  12. data/app/mailers/bulk_ops/application_mailer.rb +6 -0
  13. data/app/models/bulk_ops/application_record.rb +5 -0
  14. data/app/views/bulk_ops/_bulk_ops_sidebar_widget.html.erb +15 -0
  15. data/app/views/bulk_ops/_github_auth_widget.html.erb +13 -0
  16. data/app/views/bulk_ops/operations/_bulk_ops_header.html.erb +4 -0
  17. data/app/views/bulk_ops/operations/_choose_fields.html.erb +22 -0
  18. data/app/views/bulk_ops/operations/_choose_notifications.html.erb +22 -0
  19. data/app/views/bulk_ops/operations/_git_message.html.erb +7 -0
  20. data/app/views/bulk_ops/operations/_ingest_options.html.erb +42 -0
  21. data/app/views/bulk_ops/operations/_operation_options.html.erb +38 -0
  22. data/app/views/bulk_ops/operations/_show_authorize.html.erb +13 -0
  23. data/app/views/bulk_ops/operations/_show_complete.html.erb +31 -0
  24. data/app/views/bulk_ops/operations/_show_draft.html.erb +20 -0
  25. data/app/views/bulk_ops/operations/_show_new.html.erb +2 -0
  26. data/app/views/bulk_ops/operations/_show_pending.html.erb +58 -0
  27. data/app/views/bulk_ops/operations/_show_running.html.erb +56 -0
  28. data/app/views/bulk_ops/operations/_show_verifying.html.erb +8 -0
  29. data/app/views/bulk_ops/operations/_show_waiting.html.erb +9 -0
  30. data/app/views/bulk_ops/operations/_update_draft_work_list.html.erb +45 -0
  31. data/app/views/bulk_ops/operations/_update_draft_work_search.html.erb +59 -0
  32. data/app/views/bulk_ops/operations/_update_options.html.erb +9 -0
  33. data/app/views/bulk_ops/operations/index.html.erb +51 -0
  34. data/app/views/bulk_ops/operations/new.html.erb +36 -0
  35. data/app/views/bulk_ops/operations/show.html.erb +7 -0
  36. data/config/routes.rb +25 -0
  37. data/db/migrate/20180926190757_create_github_credentials.rb +13 -0
  38. data/db/migrate/20181017180436_create_bulk_ops_tables.rb +40 -0
  39. data/lib/bulk_ops.rb +15 -0
  40. data/lib/bulk_ops/create_spreadsheet_job.rb +43 -0
  41. data/lib/bulk_ops/create_work_job.rb +14 -0
  42. data/lib/bulk_ops/delete_file_set_job.rb +15 -0
  43. data/lib/bulk_ops/engine.rb +6 -0
  44. data/lib/bulk_ops/error.rb +141 -0
  45. data/lib/bulk_ops/github_access.rb +284 -0
  46. data/lib/bulk_ops/github_credential.rb +3 -0
  47. data/lib/bulk_ops/operation.rb +358 -0
  48. data/lib/bulk_ops/relationship.rb +79 -0
  49. data/lib/bulk_ops/search_builder_behavior.rb +80 -0
  50. data/lib/bulk_ops/templates/configuration.yml +5 -0
  51. data/lib/bulk_ops/templates/readme.md +1 -0
  52. data/lib/bulk_ops/update_work_job.rb +14 -0
  53. data/lib/bulk_ops/verification.rb +210 -0
  54. data/lib/bulk_ops/verification_job.rb +23 -0
  55. data/lib/bulk_ops/version.rb +3 -0
  56. data/lib/bulk_ops/work_job.rb +104 -0
  57. data/lib/bulk_ops/work_proxy.rb +466 -0
  58. data/lib/generators/bulk_ops/install/install_generator.rb +27 -0
  59. data/lib/generators/bulk_ops/install/templates/config/github.yml.example +28 -0
  60. metadata +145 -0
@@ -0,0 +1,79 @@
1
+ class BulkOps::Relationship < ActiveRecord::Base
2
+ RELATIONSHIP_FIELDS = ['parent','child','order','next','collection']
3
+
4
+ self.table_name = "bulk_ops_relationships"
5
+ belongs_to :work_proxy, class_name: "BulkOps::WorkProxy", foreign_key: "work_proxy_id"
6
+
7
+ def initialize *args
8
+ super *args
9
+
10
+ # Attempt to resolve the relationship immediately
11
+ # which might work in the case of updates
12
+ resolve!
13
+ end
14
+
15
+ def findObject
16
+ work_type = (relationship_type.downcase == "collection") ? "Collection" : work_proxy.work_type
17
+ case identifier_type
18
+ when "id"
19
+ begin
20
+ object = ActiveFedora::Base.find(object_identifier)
21
+ rescue Ldp::Gone
22
+ return false
23
+ end
24
+ return object || false
25
+ when "title"
26
+ # TODO clean up solr query and add work type to it
27
+ query = "{!field f=title_tesim}#{object_identifier}"
28
+ objects = ActiveFedora::SolrService.instance.conn.get(ActiveFedora::SolrService.select_path,params: { fq: query, rows: 100})["response"]["docs"].first
29
+ object = objects.first
30
+ object ||= Collection.create(title: [object_identifier]) if work_type == "Collection"
31
+ return object || false
32
+ when "identifier"
33
+ query = "{!field f=identifier_tesim}#{object_identifier}"
34
+ objects = ActiveFedora::SolrService.instance.conn.get(ActiveFedora::SolrService.select_path,params: { fq: query, rows: 100})["response"]["docs"]
35
+ return false if objects.blank?
36
+ return objects.first
37
+ end
38
+ end
39
+
40
+ def resolve! ()
41
+ unless subject = work_proxy.work and object = self.findObject
42
+ wait!
43
+ return
44
+ end
45
+ implement_relationship! relationship_type, subject, object
46
+
47
+ end
48
+
49
+ def implement_relationship!(type,subject,object)
50
+ case type
51
+ when "parent"
52
+ object.ordered_members << subject
53
+ object.save
54
+ when "child"
55
+ subject.ordered_members << object
56
+ subject.save
57
+ when "collection"
58
+ object.add_members([subject.id])
59
+ object.save
60
+ when "next"
61
+ #TODO - implement this - related to ordering of filesets
62
+ when "order"
63
+ #TODO - implement this - related to ordering of filesets
64
+
65
+ end
66
+ update(status: "complete")
67
+ end
68
+
69
+ private
70
+
71
+ def fail!
72
+ update(status: "failed")
73
+ end
74
+
75
+ def wait!
76
+ update(status: "pending")
77
+ end
78
+
79
+ end
@@ -0,0 +1,80 @@
1
+ module BulkOps::SearchBuilderBehavior
2
+ extend ActiveSupport::Concern
3
+ included do
4
+ attr_reader :collection,
5
+ :admin_set,
6
+ :workflow_state
7
+ class_attribute :collection_field,
8
+ :collection_id_field,
9
+ :admin_set_field,
10
+ :admin_set_id_field,
11
+ :workflow_state_field,
12
+ :workflow_state_id_field,
13
+ :keyword_field
14
+ self.collection_field = 'member_of_collections_ssim'
15
+ self.collection_id_field = 'member_of_collection_ids_ssim'
16
+ self.admin_set_field = 'admin_set_tesim'
17
+ self.admin_set_id_field = 'isPartOf_ssim'
18
+ self.workflow_state_field = 'workflow_state_name_ssim'
19
+ self.keyword_field = 'all_fields'
20
+
21
+ self.default_processor_chain += [:member_of_collection,
22
+ :member_of_admin_set,
23
+ :in_workflow_state,
24
+ :with_keyword_query]
25
+ end
26
+
27
+ # @param [scope] Typically the controller object
28
+ def initialize(scope: {},
29
+ collection: nil,
30
+ collection_id: nil,
31
+ admin_set: nil,
32
+ admin_set_id: nil,
33
+ workflow_state: nil,
34
+ keyword_query: nil)
35
+
36
+ @collection = collection unless collection.blank?
37
+ @admin_set = admin_set unless admin_set.blank?
38
+ @admin_set_id = admin_set_id unless admin_set_id.blank?
39
+ @workflow_state = workflow_state unless workflow_state.blank?
40
+ @collection_id = collection_id unless collection_id.blank?
41
+ @workflow_state = workflow_state unless workflow_state.blank?
42
+ @keyword_query = keyword_query unless keyword_query.blank?
43
+ super(scope)
44
+ end
45
+
46
+ def models
47
+ [Work,Course,Lecture]
48
+ end
49
+
50
+ # include filters into the query to only include the collection memebers
51
+ def member_of_collection(solr_parameters)
52
+ solr_parameters[:fq] ||= []
53
+ solr_parameters[:fq] << "#{collection_field}:#{@collection}" if @collection
54
+ solr_parameters[:fq] << "#{collection_id_field}:#{@collection_id}" if @collection_id
55
+ end
56
+
57
+ # include filters into the query to only include the collection memebers
58
+ def member_of_admin_set(solr_parameters)
59
+ solr_parameters[:fq] ||= []
60
+ solr_parameters[:fq] << "#{admin_set_field}:#{@admin_set}" if @admin_set
61
+ solr_parameters[:fq] << "#{admin_set_id_field}:#{@admin_set_id}" if @admin_set_id
62
+ end
63
+
64
+ # include filters into the query to only include the collection memebers
65
+ def in_workflow_state(solr_parameters)
66
+ solr_parameters[:fq] ||= []
67
+ solr_parameters[:fq] << "#{workflow_state_field}:#{@workflow_state}" if @workflow_state
68
+ end
69
+
70
+ def with_keyword_query(solr_parameters)
71
+ if @keyword_query
72
+ solr_parameters[:q] ||= []
73
+ # solr_parameters[:q] << "#{keyword_field}:#{@keyword_query}" if @keyword_query
74
+ solr_parameters[:q] << @keyword_query
75
+ solr_parameters[:qf] = "title_tesim titleAlternative_tesim subseries_tesim creator_label_tesim contributor_label_tesim originalPublisher_tesim publisher_tesim publisherHomepage_tesim resourceType_label_tesim rightsHolder_label_tesim scale_tesim series_tesim source_tesim staffNote_tesim coordinates_tesim subjectName_label_tesim subjectPlace_label_tesim subjectTemporal_label_tesim subjectTopic_label_tesim dateCreated_tesim dateCreatedDisplay_tesim dateDigitized_tesim datePublished_tesim description_tesim physicalFormat_label_tesim keyword_tesim language_label_tesim license_tesim masterFilename_tesim physicalDescription_tesim accessRights_tesim itemCallNumber_tesim collectionCallNumber_tesim donorProvenance_tesim genre_label_tesim boxFolder_tesim subject_label_tesim file_format_tesim all_text_timv"
76
+ end
77
+ solr_parameters
78
+ end
79
+
80
+ end
@@ -0,0 +1,5 @@
1
+ notifications:
2
+ - ethenry@ucsc.edu
3
+ name: "A Readable Branch Name (optional)"
4
+ status: New
5
+ type: "Update / Edit / Overlay"
@@ -0,0 +1 @@
1
+ This is a readme file for the specific branch. The whole repository's readme file has different information. I'm not sure if we need both, since i haven't written either yet.
@@ -0,0 +1,14 @@
1
+ #require 'hydra/access_controls'
2
+ #require 'hyrax/workflow/activate_object'
3
+
4
+ require 'bulk_ops/work_job'
5
+
6
+ class BulkOps::UpdateWorkJob < BulkOps::WorkJob
7
+
8
+ private
9
+
10
+ def type
11
+ :update
12
+ end
13
+
14
+ end
@@ -0,0 +1,210 @@
1
+ module BulkOps
2
+ module Verification
3
+ extend ActiveSupport::Concern
4
+
5
+ def verify
6
+ @verification_errors ||= []
7
+ verify_column_headers
8
+ verify_remote_urls
9
+ verify_internal_references
10
+ verify_files
11
+ verify_works_to_update if operation_type.to_s == "update"
12
+ unless @verification_errors.blank?
13
+ error_file_name = BulkOps::Error.write_errors!(@verification_errors, git)
14
+ #notify everybody
15
+ notify(subject: "Errors verifying bulk #{operation_type} in Hycruz", message: "Hyrax ran a verification step to make sure that the spreadsheet for this bulk #{operation_type} is formatted correctly and won't create any errors. We found some problems. You can see a summary of the issues at this url: https://github.com/#{git.repo}/blob/#{git.name}/#{git.name}/errors/#{error_file_name}. Please fix these problems and run this verification again. The bulk #{operation_type} will not be allowed to move forward until all verification issues are resolved.")
16
+ return false
17
+ end
18
+ return true
19
+ end
20
+
21
+ def notify(subject: , message:)
22
+ options["notifications"].each do |email|
23
+ ActionMailer::Base.mail(from: "admin@digitalcollections.library.ucsc.edu",
24
+ to: email,
25
+ subject: subject,
26
+ body: message).deliver
27
+ end
28
+ end
29
+
30
+ def is_file_field?(fieldname)
31
+ return false if fieldname.blank?
32
+ field_parts = fieldname.underscore.humanize.downcase.gsub(/[-_]/,' ').split(" ")
33
+ return false unless field_parts.any?{ |field_type| BulkOps::WorkProxy::FILE_FIELDS.include?(field_type) }
34
+ return "remove" if field_parts.any?{ |field_type| ['remove','delete'].include?(field_type) }
35
+ return "add"
36
+ end
37
+
38
+ def find_field_name(fieldname)
39
+ name = fieldname.dup
40
+ name.gsub!(/[_\s-]?[aA]ttributes$/,'')
41
+ name.gsub!(/[_\s-]?[lL]abel$/,'')
42
+ name.gsub!(/^[rR]emove[_\s-]?/,'')
43
+ name.gsub!(/^[dD]elete[_\s-]?/,'')
44
+ possible_fields = Work.attribute_names + schema.all_field_names
45
+ matching_fields = possible_fields.select{|pfield| pfield.gsub(/[_\s-]/,'').parameterize == name.gsub(/[_\s-]/,'').parameterize }
46
+ return false if matching_fields.blank?
47
+ # raise Exception "Ambiguous metadata fields!" if matching_fields.uniq.count > 1
48
+ return matching_fields.first
49
+ end
50
+
51
+ def get_file_paths(filestring)
52
+ return [] if filestring.blank?
53
+ filenames = filestring.split(BulkOps::WorkProxy::SEPARATOR)
54
+ filenames.map { |filename| File.join(BulkOps::Operation::INGEST_MEDIA_PATH, options['file_prefix'] || "", filename) }
55
+ end
56
+
57
+ def record_exists? id
58
+ begin
59
+ return true if SolrDocument.find(id)
60
+ rescue Blacklight::Exceptions::RecordNotFound
61
+ return false
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def verify_files
68
+ file_errors = []
69
+ get_spreadsheet.each_with_index do |row, row_num|
70
+ file_fields = row.select { |field, value| is_file_field?(field) }
71
+ file_fields.each do |column_name, filestring|
72
+ next if filestring.blank? or column_name == filestring
73
+ get_file_paths(filestring).each do |filepath|
74
+ file_errors << BulkOps::Error.new({type: :cannot_find_file, file: filepath}) unless File.file? filepath
75
+ end
76
+ end
77
+ end
78
+ @verification_errors.concat file_errors
79
+ return file_errors
80
+ end
81
+
82
+ def verify_configuration
83
+ BulkOps::Operation::OPTION_REQUIREMENTS.each do |option_name, option_info|
84
+ # Make sure it's present if required
85
+ if (option_info["required"].to_s == "true") || (option_info["required"].to_s == type)
86
+ if options[option_name].blank?
87
+ @verification_errors << BulkOps::Error.new({type: :missing_required_option, option_name: option_name})
88
+ end
89
+ end
90
+ # Make sure the values are acceptable if present
91
+ unless (values = option_info.values).blank? || options[option_name].blank?
92
+ unless values.include? option[option_name]
93
+ values_string = values.reduce{|a,b| "#{a}, #{b}"}
94
+ @verification_errors << BulkOps::Error.new({type: :invalid_config_value, option_name: option_name, option_values: values_string})
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def downcase_first_letter(str)
101
+ str[0].downcase + str[1..-1]
102
+ end
103
+
104
+ # Make sure the headers in the spreadsheet are matching to properties
105
+ def verify_column_headers
106
+
107
+ unless (headers = get_spreadsheet.headers)
108
+ # log an error if we can't get the metadata headers
109
+ @verification_errors << BulkOps::Error.new({type: :bad_header, field: column_name})
110
+ end
111
+
112
+ headers.each do |column_name|
113
+ next if column_name.blank?
114
+ column_name_redux = column_name.downcase.parameterize.gsub(/[_\s-]/,"")
115
+ # Ignore everything marked as a label
116
+ next if column_name_redux.ends_with? "label"
117
+ # Ignore any column names with special meaning in hyrax
118
+ next if BulkOps::Operation::SPECIAL_COLUMNS.any?{|col| col.downcase.parameterize.gsub(/[_\s-]/,"") == column_name_redux }
119
+ # Ignore any columns speficied to be ignored in the configuration
120
+ ignored = options["ignored headers"] || []
121
+ next if ignored.any?{|col| col.downcase.parameterize.gsub(/[_\s-]/,"") == column_name_redux }
122
+ # Column names corresponding to work attributes are legit
123
+ next if Work.attribute_names.any?{|col| col.downcase.parameterize.gsub(/[_\s-]/,"") == column_name_redux }
124
+ @verification_errors << BulkOps::Error.new({type: :bad_header, field: column_name})
125
+ end
126
+ end
127
+
128
+ def verify_remote_urls
129
+ get_spreadsheet.each do |row, row_num|
130
+ schema.controlled_field_names.each do |controlled_field_name|
131
+ next unless (url = row[controlled_field_name])
132
+ label = ::WorkIndexer.fetch_remote_label(url)
133
+ if !label || label.blank?
134
+ @verification_errors << BulkOps::Error.new({type: :cannot_retrieve_label, row: row_num + ROW_OFFSET, field: controlled_field_name, url: url})
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ def get_id_from_row row
141
+ ref_id = get_ref_id(row).to_sym
142
+ return :id if ref_id == :id
143
+ normrow = row.mapgsub(//,'').parameterize
144
+ if row.key?(ref_id)
145
+
146
+ # TODO if ref_id is another column
147
+ # TODO implement solr search
148
+ end
149
+ end
150
+
151
+
152
+ def verify_works_to_update
153
+ return [] unless operation_type == "update"
154
+ get_spreadsheet.each_with_index do |row, row_num|
155
+ id = get_ref_id(row)
156
+ #TODO: find by other field. for now just id
157
+ unless (record_exists(id))
158
+ @verification_errors << BulkOps::Error.new(type: :cannot_find_work, id: id)
159
+ end
160
+ end
161
+ end
162
+
163
+ def get_ref_id row
164
+ row.each do |field,value|
165
+ next if field.blank? or value.blank? or field === value
166
+ next unless BulkOps::WorkProxy::REFERENCE_IDENTIFIER_FIELDS.any?{ |ref_field| normalize_field(ref_field) == normalize_field(field) }
167
+ return value
168
+ end
169
+ # No reference identifier specified in the row. Use the default for the operation.
170
+ return reference_identifier || :id
171
+ end
172
+
173
+ def normalize_field field
174
+ return '' if field.nil?
175
+ field.downcase.parameterize.gsub(/[_\s-]/,'')
176
+ end
177
+
178
+ def verify_internal_references
179
+ # TODO
180
+ # This is sketchy. Redo it.
181
+ get_spreadsheet.each do |row,row_num|
182
+ ref_id = get_ref_id(row)
183
+ BulkOps::Operation::RELATIONSHIP_COLUMNS.each do |relationship|
184
+ next unless (obj_id = row[relationship])
185
+ if (split = obj_id.split(':')).count == 2
186
+ ref_id = split[0].downcase
187
+ obj_id = split[1]
188
+ end
189
+
190
+ if ref_id == "row" || (ref_id == "id/row" && obj_id.is_a?(Integer))
191
+ # This is a row number reference. It should be an integer in the range of possible row numbers.
192
+ unless obj_id.is_a? Integer && obj_id > 0 && obj_id <= metadata.count
193
+ @verification_errors << BulkOps::Error.new({type: :bad_object_reference, object_id: obj_id, row_number: row_num + ROW_OFFSET})
194
+ end
195
+ elsif ref_id == "id" || ref_id == "hyrax id" || (ref_id == "id/row" && (obj_id.is_a? Integer))
196
+ # This is a hydra id reference. It should correspond to an object already in the repo
197
+ unless record_exists?(obj_id)
198
+ @verification_errors << BulkOps::Error.new({type: :bad_object_reference, object_id: obj_id, row_number: row_num+ROW_OFFSET})
199
+ end
200
+ else
201
+
202
+ # This must be based on some other presumably unique field in hyrax, or a dummy field in the spreadsheet. We haven't added this functionality yet. Ignore for now.
203
+
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ end
210
+ end
@@ -0,0 +1,23 @@
1
+ #require 'hydra/access_controls'
2
+ #require 'hyrax/workflow/activate_object'
3
+
4
+ class BulkOps::VerificationJob < ActiveJob::Base
5
+
6
+ attr_accessor :operation
7
+
8
+ queue_as :default
9
+
10
+ def perform(operation)
11
+
12
+ if operation.verify
13
+ operation.set_stage "authorize"
14
+ if operation.create_pull_request
15
+ operation.notify(subject: "Bulk Operation Verification Successful", message: "Your bulk ingest has passed verification, and we have requested to start applying the operation. It may required one final approval from an administrator before the operation proceeds.")
16
+ else
17
+ operation.notify(subject: "Bulk Operation - Error creating Github pull request", message: "Your bulk ingest has passed verification, but we had a problem creating a pull request on Github in order to merge this operation with the master branch. Please check your github configuration.")
18
+ end
19
+ else
20
+ operation.set_stage "pending"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module BulkOps
2
+ VERSION = "0.1.3"
3
+ end
@@ -0,0 +1,104 @@
1
+ #require 'hydra/access_controls'
2
+ #require 'hyrax/workflow/activate_object'
3
+
4
+ class BulkOps::WorkJob < ActiveJob::Base
5
+ attr_accessor :status, :work, :type
6
+
7
+ queue_as :ingest
8
+
9
+ after_perform do |job|
10
+
11
+ # update BulkOperationsWorkProxy status
12
+ @work ||= ActiveFedora.find(@work_proxy.work_id)
13
+ if @work.id.nil?
14
+ status = "error"
15
+ else
16
+ @work_proxy.work_id = @work.id
17
+ status = "complete"
18
+ end
19
+ update_status status
20
+
21
+ # Attempt to resolve all of the relationships defined in this row
22
+ @work_proxy.relationships.each do |relationship|
23
+ relationship.resolve!
24
+ end
25
+
26
+ # Attempt to resolve each dangling (objectless) relationships using
27
+ # this work as an object
28
+ BulkOps::Relationship.where(:status => "objectless").each do |relationship|
29
+ relationship.resolve! @work.id
30
+ end
31
+
32
+ # Delete any UploadedFiles. These take up tons of unnecessary disk space.
33
+ @work.file_sets.each do |fileset|
34
+ if uf = Hyrax::UploadedFile.find_by(file: fileset.label)
35
+ uf.destroy!
36
+ end
37
+ end
38
+
39
+ # Remove any edit holds placed on an item
40
+ @work_proxy.lift_hold
41
+
42
+ # Check if the parent operation is finished
43
+ # and do any cleanup if so
44
+ @work_proxy.operation.check_if_finished
45
+ end
46
+
47
+ def perform(workClass,user_email,attributes,work_proxy_id,visibility="private")
48
+ update_status "starting", "Initializing the job"
49
+ @work_proxy = BulkOps::WorkProxy.find(work_proxy_id)
50
+ unless @work_proxy
51
+ report_error("Cannot find work proxy with id: #{work_proxy_id}")
52
+ return
53
+ end
54
+ if record_exists?(@work_proxy.work_id)
55
+ # The work exists in Solr. Presumably we're updating it.
56
+ # Report an error if we can't retrieve the work from Fedora.
57
+ begin
58
+ @work = ActiveFedora::Base.find(@work_proxy.work_id)
59
+ rescue ActiveFedora::ObjectNotFoundError
60
+ report_error "Could not find work to update in Fedora (though it shows up in Solr). Work id: #{@work_proxy.work_id}"
61
+ return
62
+ end
63
+ else # The work is not found in Solr. If we're trying to update a work, we're in trouble.
64
+ if (type == "update")
65
+ report_error "Could not find work to update with id: #{@work_proxy.work_id}"
66
+ return
67
+ end
68
+ # Create the work we are ingesting
69
+ @work = workClass.capitalize.constantize.new
70
+ end
71
+ user = User.find_by_email(user_email)
72
+ update_status "running", "Started background task at #{DateTime.now.strftime("%d/%m/%Y %H:%M")}"
73
+ ability = Ability.new(user)
74
+ env = Hyrax::Actors::Environment.new(@work, ability, attributes)
75
+ update_status "complete", Hyrax::CurationConcern.actor.send(type,env)
76
+ end
77
+
78
+ private
79
+
80
+ def record_exists? id
81
+ begin
82
+ return true if SolrDocument.find(id)
83
+ rescue Blacklight::Exceptions::RecordNotFound
84
+ return false
85
+ end
86
+ end
87
+
88
+ def report_error message=nil
89
+ update_status "job_error", message: message
90
+ end
91
+
92
+ def type
93
+ #override this, setting as ingest by default
94
+ :create
95
+ end
96
+
97
+ def update_status status, message=false
98
+ return false unless @work_proxy
99
+ atts = {status: status}
100
+ atts[:message] = message if message
101
+ @work_proxy.update(atts)
102
+ end
103
+
104
+ end