Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions cms/djangoapps/contentstore/management/commands/fix_not_found.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
Script for fixing the item not found errors in a course
"""
from django.core.management.base import BaseCommand, CommandError
from opaque_keys.edx.keys import CourseKey
from xmodule.modulestore.django import modulestore
from xmodule.modulestore import ModuleStoreEnum

# To run from command line: ./manage.py cms fix_not_found course-v1:org+course+run


class Command(BaseCommand):
"""Fix a course's item not found errors"""
help = "Fix a course's ItemNotFound errors"

def handle(self, *args, **options):
"Execute the command"
if len(args) != 1:
raise CommandError("requires 1 argument: <course_id>")

course_key = CourseKey.from_string(args[0])
# for now only support on split mongo
owning_store = modulestore()._get_modulestore_for_courseid(course_key)
if hasattr(owning_store, 'fix_not_found'):
owning_store.fix_not_found(course_key, ModuleStoreEnum.UserID.mgmt_command)
else:
raise CommandError("The owning modulestore does not support this command.")
2 changes: 1 addition & 1 deletion common/lib/xmodule/xmodule/modulestore/split_migrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def _copy_published_modules_to_course(self, new_course, old_course_loc, source_c

# clean up orphans in published version: in old mongo, parents pointed to the union of their published and draft
# children which meant some pointers were to non-existent locations in 'direct'
self.split_modulestore.internal_clean_children(course_version_locator)
self.split_modulestore.fix_not_found(course_version_locator, user_id)

def _add_draft_modules_to_course(self, published_course_usage_key, source_course_key, user_id, **kwargs):
"""
Expand Down
16 changes: 10 additions & 6 deletions common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
Original file line number Diff line number Diff line change
Expand Up @@ -2418,22 +2418,26 @@ def copy_all_asset_metadata(self, source_course_key, dest_course_key, user_id):
# update the index entry if appropriate
self._update_head(dest_course_key, index_entry, dest_course_key.branch, new_structure['_id'])

def internal_clean_children(self, course_locator):
def fix_not_found(self, course_locator, user_id):
"""
Only intended for rather low level methods to use. Goes through the children attrs of
each block removing any whose block_id is not a member of the course. Does not generate
a new version of the course but overwrites the existing one.
each block removing any whose block_id is not a member of the course.

:param course_locator: the course to clean
"""
original_structure = self._lookup_course(course_locator).structure
for block in original_structure['blocks'].itervalues():
index_entry = self._get_index_if_valid(course_locator)
new_structure = self.version_structure(course_locator, original_structure, user_id)
for block in new_structure['blocks'].itervalues():
if 'fields' in block and 'children' in block['fields']:
block['fields']["children"] = [
block_id for block_id in block['fields']["children"]
if block_id in original_structure['blocks']
if block_id in new_structure['blocks']
]
self.update_structure(course_locator, original_structure)
self.update_structure(course_locator, new_structure)
if index_entry is not None:
# update the index entry if appropriate
self._update_head(course_locator, index_entry, course_locator.branch, new_structure['_id'])

def convert_references_to_keys(self, course_key, xblock_class, jsonfields, blocks):
"""
Expand Down
10 changes: 10 additions & 0 deletions common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,16 @@ def get_orphans(self, course_key, **kwargs):
course_key = self._map_revision_to_branch(course_key)
return super(DraftVersioningModuleStore, self).get_orphans(course_key, **kwargs)

def fix_not_found(self, course_key, user_id):
"""
Fix any children which point to non-existent blocks in the course's published and draft branches
"""
for branch in [ModuleStoreEnum.RevisionOption.published_only, ModuleStoreEnum.RevisionOption.draft_only]:
super(DraftVersioningModuleStore, self).fix_not_found(
self._map_revision_to_branch(course_key, branch),
user_id
)

def has_changes(self, xblock):
"""
Checks if the given block has unpublished changes
Expand Down
Binary file modified conf/locale/es_419/LC_MESSAGES/django.mo
Binary file not shown.
2 changes: 1 addition & 1 deletion conf/locale/es_419/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -10613,7 +10613,7 @@ msgstr "Gracias por su paciencia mientras se procesa su solicitud."

#: lms/templates/dashboard/_dashboard_course_listing.html
msgid "Your verification status is good until {date}."
msgstr "Su estado de verificación es bueno hasta {fecha}"
msgstr "Su estado de verificación es bueno hasta {date}"

#: lms/templates/dashboard/_dashboard_course_listing.html
msgid "Challenge Yourself!"
Expand Down