Skip to content

Commit 05818d2

Browse files
committed
Rule 4: Parent visibility ceiling
A child document may not be more publicly visible than its parent document. | Parent | Allowed child states | |-------------|-------------------------------------| | published | published / withdrawn / unpublished | | withdrawn | withdrawn / unpublished | | unpublished | unpublished | Implementation wise, we **could** auto-cascade such that if you unpublish the parent, you unpublish its children. But it gets messy if there exists a draft child - do you auto-discard the draft in order to unpublish it? Etc. So to begin with at least, we will force the publisher to manually withdraw/unpublish (as appropriate) all of a document's children before withdrawing/unpublishing the parent document. This simplified interpretation can be summarised as "You cannot withdraw/unpublish a parent while any children remain more publicly visible than it."
1 parent f3a8658 commit 05818d2

4 files changed

Lines changed: 110 additions & 0 deletions

File tree

app/controllers/admin/edition_workflow_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ def unpublish
114114
flash.now[:alert] = message if @unpublishing.errors.blank?
115115
render :confirm_unpublish
116116
end
117+
rescue WhitehallError => e
118+
redirect_to admin_edition_path(@edition), alert: e.message
117119
end
118120

119121
def confirm_unwithdraw; end

app/models/concerns/standard_edition/parent_document.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ module StandardEdition::ParentDocument
22
extend ActiveSupport::Concern
33

44
class UnableToDelete < ::WhitehallError; end
5+
class UnableToWithdraw < ::WhitehallError; end
6+
class UnableToUnpublish < ::WhitehallError; end
57

68
class Trait < Edition::Traits::Trait
79
def process_associations_after_save(new_edition)
@@ -33,6 +35,7 @@ def process_associations_after_save(new_edition)
3335
source: :child_document
3436

3537
before_update :ensure_no_new_child_documents!, if: :deleting?
38+
before_update :ensure_no_children_more_visible_than_parent!, if: :will_save_change_to_state?
3639

3740
add_trait Trait
3841
end
@@ -64,4 +67,14 @@ def ensure_no_new_child_documents!
6467
raise UnableToDelete, "This document cannot be deleted while it has child documents that have never been published. Delete the draft child documents first."
6568
end
6669
end
70+
71+
def ensure_no_children_more_visible_than_parent!
72+
if state == "unpublished" && child_editions.any? { |child| child.state.in?(%w[published withdrawn]) }
73+
raise UnableToUnpublish, "This document cannot be unpublished while it has child documents that are published or withdrawn. Unpublish the child documents first."
74+
end
75+
76+
if state == "withdrawn" && child_editions.any? { |child| child.state == "published" }
77+
raise UnableToWithdraw, "This document cannot be withdrawn while it has child documents that are published. Withdraw the child documents first."
78+
end
79+
end
6780
end

test/functional/admin/edition_workflow_controller_test.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,18 @@ class Admin::EditionWorkflowControllerTest < ActionController::TestCase
388388
assert published_edition.reload.published?
389389
end
390390

391+
test "#unpublish catches WhitehallError and redirects with an alert" do
392+
Whitehall.edition_services.stubs(:unpublisher).raises(WhitehallError.new("Something went wrong"))
393+
login_as create(:managing_editor)
394+
unpublish_params = {
395+
unpublishing_reason_id: UnpublishingReason::Consolidated.id,
396+
alternative_url: "https://www.gov.uk/alternative",
397+
}
398+
post :unpublish, params: { id: published_edition, lock_version: published_edition.lock_version, unpublishing: unpublish_params }
399+
assert_redirected_to admin_publication_path(published_edition)
400+
assert_equal "Something went wrong", flash[:alert]
401+
end
402+
391403
view_test "#unpublish when there are validation errors re-renders the unpublish form" do
392404
login_as create(:managing_editor)
393405
unpublish_params = {

test/unit/app/models/concerns/standard_edition/parent_document_test.rb

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,87 @@ class StandardEdition::ParentDocumentTest < ActiveSupport::TestCase
239239

240240
assert_equal "This document cannot be deleted while it has child documents that have never been published. Delete the draft child documents first.", error.message
241241
end
242+
243+
test "able to unpublish parent edition if all of its children are already unpublished" do
244+
parent_edition = create(:standard_edition)
245+
246+
child_edition = create(:unpublished_standard_edition)
247+
build(
248+
:parent_child_relationship,
249+
parent_edition: parent_edition,
250+
child_document: child_edition.document,
251+
).save!(validate: false)
252+
253+
assert_nothing_raised do
254+
parent_edition.update!(state: "unpublished")
255+
end
256+
end
257+
258+
test "able to withdraw parent edition if all of its children are already unpublished or withdrawn" do
259+
parent_edition = create(:standard_edition)
260+
child_edition_1 = create(:unpublished_standard_edition)
261+
child_edition_2 = create(:withdrawn_standard_edition)
262+
[child_edition_1, child_edition_2].each do |child_edition|
263+
build(
264+
:parent_child_relationship,
265+
parent_edition: parent_edition,
266+
child_document: child_edition.document,
267+
).save!(validate: false)
268+
end
269+
270+
assert_nothing_raised do
271+
parent_edition.update!(state: "withdrawn")
272+
end
273+
end
274+
275+
test "unable to unpublish parent edition if it contains any published child documents" do
276+
parent_edition = create(:standard_edition)
277+
278+
child_edition = create(:published_standard_edition)
279+
build(
280+
:parent_child_relationship,
281+
parent_edition: parent_edition,
282+
child_document: child_edition.document,
283+
).save!(validate: false)
284+
285+
error = assert_raises(StandardEdition::ParentDocument::UnableToUnpublish) do
286+
parent_edition.update!(state: "unpublished")
287+
end
288+
289+
assert_equal "This document cannot be unpublished while it has child documents that are published or withdrawn. Unpublish the child documents first.", error.message
290+
end
291+
292+
test "unable to unpublish parent edition if it contains any withdrawn child documents" do
293+
parent_edition = create(:standard_edition)
294+
295+
child_edition = create(:withdrawn_standard_edition)
296+
build(
297+
:parent_child_relationship,
298+
parent_edition: parent_edition,
299+
child_document: child_edition.document,
300+
).save!(validate: false)
301+
302+
error = assert_raises(StandardEdition::ParentDocument::UnableToUnpublish) do
303+
parent_edition.update!(state: "unpublished")
304+
end
305+
306+
assert_equal "This document cannot be unpublished while it has child documents that are published or withdrawn. Unpublish the child documents first.", error.message
307+
end
308+
309+
test "unable to withdraw parent edition if it contains any published child documents" do
310+
parent_edition = create(:standard_edition)
311+
312+
child_edition = create(:published_standard_edition)
313+
build(
314+
:parent_child_relationship,
315+
parent_edition: parent_edition,
316+
child_document: child_edition.document,
317+
).save!(validate: false)
318+
319+
error = assert_raises(StandardEdition::ParentDocument::UnableToWithdraw) do
320+
parent_edition.update!(state: "withdrawn")
321+
end
322+
323+
assert_equal "This document cannot be withdrawn while it has child documents that are published. Withdraw the child documents first.", error.message
324+
end
242325
end

0 commit comments

Comments
 (0)