also support a link rewriting on course import and clone for the following format /courses/[org]/[course]/[run]/. We just need to substitute in the new course-id.
This commit is contained in:
@@ -40,13 +40,17 @@ def _jump_to_url_replace_regex(prefix):
|
||||
""".format(prefix=prefix)
|
||||
|
||||
|
||||
def convert_to_portable_links(source_course_id, text):
|
||||
def rewrite_nonportable_content_links(source_course_id, dest_course_id, text):
|
||||
"""
|
||||
Does a regex replace on non-portable links:
|
||||
/c4x/<org>/<course>/asset/<name> -> /static/<name>
|
||||
/jump_to/i4x://<org>/<course>/<category>/<name> -> /jump_to_id/<id>
|
||||
|
||||
"""
|
||||
|
||||
org, course, run = source_course_id.split("/")
|
||||
dest_org, dest_course, dest_run = dest_course_id.split("/")
|
||||
|
||||
def portable_asset_link_subtitution(match):
|
||||
quote = match.group('quote')
|
||||
rest = match.group('rest')
|
||||
@@ -57,15 +61,50 @@ def convert_to_portable_links(source_course_id, text):
|
||||
rest = match.group('rest')
|
||||
return "".join([quote, '/jump_to_id/'+rest, quote])
|
||||
|
||||
org, course, run = source_course_id.split("/")
|
||||
def generic_courseware_link_substitution(match):
|
||||
quote = match.group('quote')
|
||||
rest = match.group('rest')
|
||||
dest_generic_courseware_lik_base = '/courses/{org}/{course}/{run}/'.format(
|
||||
org=dest_org, course=dest_course, run=dest_run)
|
||||
|
||||
return "".join([quote, dest_generic_courseware_lik_base+rest, quote])
|
||||
|
||||
course_location = Location(['i4x', org, course, 'course', run])
|
||||
|
||||
c4x_link_base = '{0}/'.format(StaticContent.get_base_url_path_for_course_assets(course_location))
|
||||
text = re.sub(_asset_url_replace_regex(c4x_link_base), portable_asset_link_subtitution, text)
|
||||
# NOTE: ultimately link updating is not a hard requirement, so if something blows up with
|
||||
# the regex subsitution, log the error and continue
|
||||
try:
|
||||
c4x_link_base = '{0}/'.format(StaticContent.get_base_url_path_for_course_assets(course_location))
|
||||
text = re.sub(_asset_url_replace_regex(c4x_link_base), portable_asset_link_subtitution, text)
|
||||
except Exception, e:
|
||||
logging.warning("Error going regex subtituion (0) on text = {1}.\n\nError msg = {2}".format(
|
||||
c4x_link_base, text, str(e)))
|
||||
pass
|
||||
|
||||
jump_to_link_base = '/courses/{org}/{course}/{run}/jump_to/i4x://{org}/{course}/'.format(
|
||||
org=org, course=course, run=run)
|
||||
text = re.sub(_jump_to_url_replace_regex(jump_to_link_base), portable_jump_to_link_substitution, text)
|
||||
try:
|
||||
jump_to_link_base = '/courses/{org}/{course}/{run}/jump_to/i4x://{org}/{course}/'.format(
|
||||
org=org, course=course, run=run)
|
||||
text = re.sub(_jump_to_url_replace_regex(jump_to_link_base), portable_jump_to_link_substitution, text)
|
||||
except Exception, e:
|
||||
logging.warning("Error going regex subtituion (0) on text = {1}.\n\nError msg = {2}".format(
|
||||
jump_to_link_base, text, str(e)))
|
||||
pass
|
||||
|
||||
# Also, there commonly is a set of link URL's used in the format:
|
||||
# /courses/<org>/<course>/<run> which will be broken if migrated to a different course_id
|
||||
# so let's rewrite those, but the target will also be non-portable,
|
||||
#
|
||||
# Note: we only need to do this if we are changing course-id's
|
||||
#
|
||||
if source_course_id != dest_course_id:
|
||||
try:
|
||||
generic_courseware_link_base = '/courses/{org}/{course}/{run}/'.format(
|
||||
org=org, course=course, run=run)
|
||||
text = re.sub(_asset_url_replace_regex(generic_courseware_link_base), portable_asset_link_subtitution, text)
|
||||
except Exception, e:
|
||||
logging.warning("Error going regex subtituion (0) on text = {1}.\n\nError msg = {2}".format(
|
||||
generic_courseware_link_base, text, str(e)))
|
||||
pass
|
||||
|
||||
return text
|
||||
|
||||
@@ -87,7 +126,8 @@ def _clone_modules(modulestore, modules, source_location, dest_location):
|
||||
# NOTE: usage of the the internal module.xblock_kvs._data does not include any 'default' values for the fields
|
||||
data = module.xblock_kvs._data
|
||||
if isinstance(data, basestring):
|
||||
data = convert_to_portable_links(source_location.course_id, data)
|
||||
data = rewrite_nonportable_content_links(
|
||||
source_location.course_id, dest_location.course_id, data)
|
||||
|
||||
modulestore.update_item(module.location, data)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ from xmodule.modulestore import Location
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from .inheritance import own_metadata
|
||||
from xmodule.errortracker import make_error_tracker
|
||||
from .store_utilities import convert_to_portable_links
|
||||
from .store_utilities import rewrite_nonportable_content_links
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -128,7 +128,8 @@ def import_from_xml(store, data_dir, course_dirs=None,
|
||||
{"type": "discussion", "name": "Discussion"},
|
||||
{"type": "wiki", "name": "Wiki"}] # note, add 'progress' when we can support it on Edge
|
||||
|
||||
import_module(module, store, course_data_path, static_content_store, course_location)
|
||||
import_module(module, store, course_data_path, static_content_store, course_location,
|
||||
target_location_namespace if target_location_namespace else course_location)
|
||||
|
||||
course_items.append(module)
|
||||
|
||||
@@ -155,7 +156,8 @@ def import_from_xml(store, data_dir, course_dirs=None,
|
||||
if verbose:
|
||||
log.debug('importing module location {0}'.format(module.location))
|
||||
|
||||
import_module(module, store, course_data_path, static_content_store, course_location)
|
||||
import_module(module, store, course_data_path, static_content_store, course_location,
|
||||
target_location_namespace if target_location_namespace else course_location)
|
||||
|
||||
# now import any 'draft' items
|
||||
if draft_store is not None:
|
||||
@@ -173,7 +175,8 @@ def import_from_xml(store, data_dir, course_dirs=None,
|
||||
return xml_module_store, course_items
|
||||
|
||||
|
||||
def import_module(module, store, course_data_path, static_content_store, source_course_location, allow_not_found=False):
|
||||
def import_module(module, store, course_data_path, static_content_store,
|
||||
source_course_location, dest_course_location, allow_not_found=False):
|
||||
content = {}
|
||||
for field in module.fields:
|
||||
if field.scope != Scope.content:
|
||||
@@ -193,7 +196,8 @@ def import_module(module, store, course_data_path, static_content_store, source_
|
||||
if isinstance(module_data, basestring):
|
||||
# we want to convert all 'non-portable' links in the module_data (if it is a string) to
|
||||
# portable strings (e.g. /static/)
|
||||
module_data = convert_to_portable_links(source_course_location.course_id, module_data)
|
||||
module_data = rewrite_nonportable_content_links(
|
||||
source_course_location.course_id, dest_course_location.course_id, module_data)
|
||||
|
||||
if allow_not_found:
|
||||
store.update_item(module.location, module_data, allow_not_found=allow_not_found)
|
||||
@@ -265,7 +269,8 @@ def import_course_draft(xml_module_store, store, draft_store, course_data_path,
|
||||
del module.xml_attributes['parent_sequential_url']
|
||||
del module.xml_attributes['index_in_children_list']
|
||||
|
||||
import_module(module, draft_store, course_data_path, static_content_store, source_location_namespace, allow_not_found=True)
|
||||
import_module(module, draft_store, course_data_path, static_content_store,
|
||||
source_location_namespace, target_location_namespace, allow_not_found=True)
|
||||
for child in module.get_children():
|
||||
_import_module(child)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user