add ability to delete published orphans from courses (PLAT-832)

fix quality violations

create child parent mapping to avoid potential performance hit when deleting items
This commit is contained in:
Adam Palay
2015-09-11 12:54:58 -04:00
parent 8834bbad90
commit 8aa23de55a
6 changed files with 104 additions and 19 deletions

View File

@@ -3,6 +3,8 @@
import ddt
from django.core.management import call_command
from contentstore.tests.test_orphan import TestOrphanBase
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore import ModuleStoreEnum
@@ -42,3 +44,68 @@ class TestDeleteOrphan(TestOrphanBase):
self.assertFalse(self.store.has_item(course.id.make_usage_key('vertical', 'OrphanVert')))
self.assertFalse(self.store.has_item(course.id.make_usage_key('chapter', 'OrphanChapter')))
self.assertFalse(self.store.has_item(course.id.make_usage_key('html', 'OrphanHtml')))
def test_delete_orphans_published_branch_split(self):
"""
Tests that if there are orphans only on the published branch,
running delete orphans with a course key that specifies
the published branch will delete the published orphan
"""
course, orphan = self.create_split_course_with_published_orphan()
published_branch = course.id.for_branch(ModuleStoreEnum.BranchName.published)
items_in_published = self.store.get_items(published_branch)
items_in_draft_preferred = self.store.get_items(course.id)
# call delete orphans, specifying the published branch
# of the course
call_command('delete_orphans', unicode(published_branch), 'commit')
# now all orphans should be deleted
self.assertOrphanCount(course.id, 0)
self.assertOrphanCount(published_branch, 0)
self.assertNotIn(orphan, self.store.get_items(published_branch))
# we should have one fewer item in the published branch of the course
self.assertEqual(
len(items_in_published) - 1,
len(self.store.get_items(published_branch)),
)
# and the same amount of items in the draft branch of the course
self.assertEqual(
len(items_in_draft_preferred),
len(self.store.get_items(course.id)),
)
def create_split_course_with_published_orphan(self):
"""
Helper to create a split course with a published orphan
"""
course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split)
# create an orphan
orphan = self.store.create_item(
self.user.id, course.id, 'html', "PublishedOnlyOrphan"
)
self.store.publish(orphan.location, self.user.id)
# grab the published branch of the course
published_branch = course.id.for_branch(
ModuleStoreEnum.BranchName.published
)
# assert that this orphan is present in both branches
self.assertOrphanCount(course.id, 1)
self.assertOrphanCount(published_branch, 1)
# delete this orphan from the draft branch without
# auto-publishing this change to the published branch
self.store.delete_item(
orphan.location, self.user.id, skip_auto_publish=True
)
# now there should be no orphans in the draft branch, but
# there should be one in published
self.assertOrphanCount(course.id, 0)
self.assertOrphanCount(published_branch, 1)
self.assertIn(orphan, self.store.get_items(published_branch))
return course, orphan

View File

@@ -16,7 +16,7 @@ class TestFixNotFound(ModuleStoreTestCase):
"""
The management command doesn't work on non split courses
"""
course = CourseFactory(default_store=ModuleStoreEnum.Type.mongo)
course = CourseFactory.create(default_store=ModuleStoreEnum.Type.mongo)
with self.assertRaises(SystemExit):
call_command("fix_not_found", unicode(course.id))

View File

@@ -60,6 +60,13 @@ class TestOrphanBase(CourseTestCase):
return course
def assertOrphanCount(self, course_key, number):
"""
Asserts that we have the expected count of orphans
for a given course_key
"""
self.assertEqual(len(self.store.get_orphans(course_key)), number)
@ddt.ddt
class TestOrphan(TestOrphanBase):

View File

@@ -702,10 +702,14 @@ def _delete_orphans(course_usage_key, user_id, commit=False):
"""
store = modulestore()
items = store.get_orphans(course_usage_key)
branch = course_usage_key.branch
if commit:
for itemloc in items:
# need to delete all versions
store.delete_item(itemloc, user_id, revision=ModuleStoreEnum.RevisionOption.all)
revision = ModuleStoreEnum.RevisionOption.all
# specify branches when deleting orphans
if branch == ModuleStoreEnum.BranchName.published:
revision = ModuleStoreEnum.RevisionOption.published_only
store.delete_item(itemloc, user_id, revision=revision)
return [unicode(item) for item in items]