Skip to content

Commit 4f8a913

Browse files
committed
feat: allow block publish if was published before Library v2 migration
1 parent 6cb1e4f commit 4f8a913

3 files changed

Lines changed: 87 additions & 3 deletions

File tree

cms/djangoapps/contentstore/tasks.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2340,12 +2340,20 @@ def _cancel_old_tasks(course_key: str, user: User, ignore_task_ids: list[str]):
23402340

23412341

23422342
@shared_task(base=LegacyLibraryContentToItemBank, bind=True)
2343-
def migrate_course_legacy_library_blocks_to_item_bank(self, user_id: int, course_key: str):
2343+
def migrate_course_legacy_library_blocks_to_item_bank(
2344+
self, user_id: int, course_key: str, publish_if_was_published: bool = False,
2345+
):
23442346
"""
23452347
Migrate legacy course library blocks to Item Bank.
23462348
23472349
Depending on the number of blocks and its children blocks this operation can take a significant
23482350
amount of time and this is why it is run as a celery task.
2351+
2352+
Arguments:
2353+
user_id: id of the user performing the migration.
2354+
course_key: the course whose legacy library content blocks should be migrated.
2355+
publish_if_was_published: if True, blocks that were published before the migration are
2356+
re-published afterwards. Defaults to False, leaving migrated blocks as drafts.
23492357
"""
23502358
ensure_cms("Legacy library content references may only be executed in CMS")
23512359
set_code_owner_attribute_from_module(__name__)
@@ -2363,7 +2371,7 @@ def migrate_course_legacy_library_blocks_to_item_bank(self, user_id: int, course
23632371
with store.bulk_operations(key):
23642372
for block in blocks:
23652373
self.status.set_state(f'Migrating block: {block.usage_key}')
2366-
block.v2_update_children_upstream_version(user_id)
2374+
block.v2_update_children_upstream_version(user_id, publish_if_was_published)
23672375
except Exception as exc: # pylint: disable=broad-except
23682376
LOGGER.exception(f'Error while migrating blocks: {exc}')
23692377
self.status.fail(str(exc))

xmodule/library_content_block.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,14 +329,18 @@ def studio_post_paste(self, store, source_node) -> bool:
329329
self.sync_from_library(upgrade_to_latest=False)
330330
return True # Children have been handled
331331

332-
def v2_update_children_upstream_version(self, user_id=None):
332+
def v2_update_children_upstream_version(self, user_id=None, publish_if_was_published=False):
333333
"""
334334
Update the upstream and upstream version fields of all children to point to library v2 version of the legacy
335335
library blocks. This essentially converts this legacy block to new ItemBankBlock.
336+
337+
If `publish_if_was_published` is True, and this block was published prior to the migration, it is
338+
re-published afterwards so that the upstream/upstream_version changes reach LMS.
336339
"""
337340
from cms.djangoapps.modulestore_migrator import api as migrator_api
338341
store = modulestore()
339342
with store.bulk_operations(self.course_id):
343+
was_published = publish_if_was_published and store.has_published_version(self)
340344
children = self.get_children()
341345
# These are the v1 library item upstream UsageKeys
342346
child_old_upstream_keys = [
@@ -358,6 +362,8 @@ def v2_update_children_upstream_version(self, user_id=None):
358362
self.is_migrated_to_v2 = True
359363
self.save()
360364
store.update_item(self, user_id)
365+
if was_published:
366+
store.publish(self.location, user_id)
361367

362368
def _validate_library_version(self, validation, lib_tools, version, library_key):
363369
"""

xmodule/tests/test_library_content.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,3 +826,73 @@ def test_author_view(self):
826826
assert '<li>html 2</li>' in rendered.content
827827
assert '<li>html 3</li>' in rendered.content
828828
assert '<li>html 4</li>' in rendered.content
829+
830+
831+
class TestLegacyLibraryContentBlockMigrationPublishing(LegacyLibraryContentTest):
832+
"""
833+
Unit tests for the `publish_if_was_published` flag of
834+
LegacyLibraryContentBlock.v2_update_children_upstream_version.
835+
"""
836+
837+
def setUp(self):
838+
from cms.djangoapps.modulestore_migrator import api
839+
from cms.djangoapps.modulestore_migrator.data import CompositionLevel, RepeatHandlingStrategy
840+
super().setUp()
841+
user = UserFactory()
842+
self._sync_lc_block_from_library()
843+
self.organization = OrganizationFactory(short_name="myorg")
844+
lib_api.create_library(
845+
org=self.organization,
846+
slug="mylib",
847+
title="My Test V2 Library",
848+
)
849+
self.library_v2 = lib_api.ContentLibrary.objects.get(slug="mylib")
850+
api.start_migration_to_library(
851+
user=user,
852+
source_key=self.library.location.library_key,
853+
target_library_key=self.library_v2.library_key,
854+
target_collection_slug=None,
855+
composition_level=CompositionLevel.Component,
856+
repeat_handling_strategy=RepeatHandlingStrategy.Skip,
857+
preserve_url_slugs=True,
858+
forward_source_to_target=True,
859+
)
860+
861+
def test_publishes_block_that_was_previously_published(self):
862+
"""
863+
If the LC block was published before migration, and `publish_if_was_published=True`,
864+
the migration should re-publish it so the new upstream links reach the published branch.
865+
"""
866+
self.store.publish(self.course.location, self.user_id)
867+
868+
self.lc_block.v2_update_children_upstream_version(self.user_id, publish_if_was_published=True)
869+
870+
with self.store.branch_setting(ModuleStoreEnum.Branch.published_only):
871+
published_block = self.store.get_item(self.lc_block.location)
872+
assert published_block.is_migrated_to_v2 is True
873+
assert published_block.get_children()[0].upstream == "lb:myorg:mylib:html:html_1"
874+
875+
def test_does_not_publish_when_flag_is_false(self):
876+
"""
877+
Even if the block was published before migration, it should NOT be re-published
878+
when `publish_if_was_published` is False (the default).
879+
"""
880+
self.store.publish(self.course.location, self.user_id)
881+
882+
self.lc_block.v2_update_children_upstream_version(self.user_id)
883+
884+
with self.store.branch_setting(ModuleStoreEnum.Branch.published_only):
885+
published_block = self.store.get_item(self.lc_block.location)
886+
# The published version still reflects the pre-migration state.
887+
assert published_block.is_migrated_to_v2 is False
888+
889+
def test_does_not_publish_block_that_was_never_published(self):
890+
"""
891+
If the LC block was never published, `publish_if_was_published=True` should not
892+
cause it to become published.
893+
"""
894+
assert not self.store.has_published_version(self.lc_block)
895+
896+
self.lc_block.v2_update_children_upstream_version(self.user_id, publish_if_was_published=True)
897+
898+
assert not self.store.has_published_version(self.store.get_item(self.lc_block.location))

0 commit comments

Comments
 (0)