From a0ea1de97e3e8c0b5e027aa18beff608476d8e7e Mon Sep 17 00:00:00 2001 From: Jeremy Friesen Date: Thu, 18 Jan 2024 15:36:25 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=81=20Add=20listener=20for=20handling?= =?UTF-8?q?=20file=20set=20attachment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why a listener and not a transaction? In part because the moment I want to perform the conditional enqueuing is at the point where the `Hyrax::WorkUploadsHandler` does it's job. That is when we have: - the parent work - the file set - the original file - the user The `Hyrax::WorkUploadsHandler` is most analogous to the behavior in `Hyrax::Actors::FileSetActor#attach_to_work` and `Hyrax::Actors::FileSetActor#create_content`. Fortunately, Hyrax's transaction and upload handler remove the conditional handling we needed between uploading a remote file and directly uploading a file. Related to: - https://github.com/scientist-softserv/hykuup_knapsack/issues/35 - https://github.com/scientist-softserv/hykuup_knapsack/issues/99 - https://github.com/scientist-softserv/iiif_print/issues/312 --- app/listeners/iiif_print/listener.rb | 33 ++++++++++++++++++++++ lib/iiif_print/engine.rb | 2 ++ spec/listeners/iiif_print/listener_spec.rb | 33 ++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 app/listeners/iiif_print/listener.rb create mode 100644 spec/listeners/iiif_print/listener_spec.rb diff --git a/app/listeners/iiif_print/listener.rb b/app/listeners/iiif_print/listener.rb new file mode 100644 index 00000000..376e21d6 --- /dev/null +++ b/app/listeners/iiif_print/listener.rb @@ -0,0 +1,33 @@ +## +# @see https://github.com/samvera/hyrax/wiki/Hyrax's-Event-Bus-(Hyrax::Publisher) +# @see https://www.rubydoc.info/gems/hyrax/Hyrax/Publisher +# @see https://dry-rb.org/gems/dry-events +module IiifPrint + class Listener + ## + # Responsible for conditionally enqueuing the creation of child works from a PDF. + # + # @param event [#[]] a hash like construct with keys :user and :file_set + # @param service [#conditionally_enqueue] + # + # @see Hyrax::WorkUploadsHandler + def on_file_set_attached(event, service: IiifPrint::SplitPdfs::ChildWorkCreationFromPdfService) + user = event[:user] + file_set = event[:file_set] + + return false unless file_set + return false unless file_set.file_set? + + work = IiifPrint.parent_for(file_set) + + # A short-circuit to avoid fetching the underlying file. + return false unless work + + # TODO: Verify that this is the correct thing to be sending off for conditional enquing. That + # will require a more involved integration test. + file = file_set.original_file + + service.conditionally_enqueue(file_set: file_set, work: work, file: file, user: user) + end + end +end diff --git a/lib/iiif_print/engine.rb b/lib/iiif_print/engine.rb index 04a5596f..de4166fc 100644 --- a/lib/iiif_print/engine.rb +++ b/lib/iiif_print/engine.rb @@ -46,6 +46,8 @@ class Engine < ::Rails::Engine IiifPrint::PluggableDerivativeService ) + Hyrax.publisher.subscribe(IiifPrint::Listener.new) + Hyrax::IiifManifestPresenter.prepend(IiifPrint::IiifManifestPresenterBehavior) Hyrax::IiifManifestPresenter::Factory.prepend(IiifPrint::IiifManifestPresenterFactoryBehavior) Hyrax::ManifestBuilderService.prepend(IiifPrint::ManifestBuilderServiceBehavior) diff --git a/spec/listeners/iiif_print/listener_spec.rb b/spec/listeners/iiif_print/listener_spec.rb new file mode 100644 index 00000000..3477cbbd --- /dev/null +++ b/spec/listeners/iiif_print/listener_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe IiifPrint::Listener do + describe '#on_file_set_attached' do + subject { described_class.new.on_file_set_attached(event) } + let(:file_set) { double(Hyrax::FileSet, file_set?: true) } + let(:user) { double(User) } + let(:event) { { user: user, file_set: file_set } } + + before { allow(IiifPrint).to receive(:parent_for).with(file_set).and_return(parent) } + + context 'without a parent work' do + let(:parent) { nil } + + it "does not call the service's #conditionally_enqueue method" do + expect(IiifPrint::SplitPdfs::ChildWorkCreationFromPdfService).not_to receive(:conditionally_enqueue) + subject + end + end + + context 'with a parent work' do + let(:parent) { double(Valkyrie::Resource) } + + it "calls the service's #conditionally_enqueue method" do + expect(IiifPrint::SplitPdfs::ChildWorkCreationFromPdfService).to receive(:conditionally_enqueue) + expect(file_set).to receive(:original_file).and_return(double) + subject + end + end + end +end