diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py
index 202d9d7e51..b375b1845f 100644
--- a/common/lib/xmodule/xmodule/html_module.py
+++ b/common/lib/xmodule/xmodule/html_module.py
@@ -116,8 +116,12 @@ class HtmlBlock(
def get_html(self):
""" Returns html required for rendering the block. """
- if self.data is not None and getattr(self.system, 'anonymous_student_id', None) is not None:
- return self.data.replace("%%USER_ID%%", self.system.anonymous_student_id)
+ if self.data:
+ data = self.data
+ if getattr(self.runtime, 'anonymous_student_id', None):
+ data = data.replace("%%USER_ID%%", self.runtime.anonymous_student_id)
+ data = data.replace("%%COURSE_ID%%", str(self.scope_ids.usage_id.context_key))
+ return data
return self.data
def studio_view(self, _context):
@@ -459,10 +463,9 @@ class CourseInfoBlock(CourseInfoFields, HtmlBlock):
# When we switch this to an XBlock, we can merge this with student_view,
# but for now the XModule mixin requires that this method be defined.
- if self.data != "":
- if self.system.anonymous_student_id:
- return self.data.replace("%%USER_ID%%", self.system.anonymous_student_id)
- return self.data
+ data = super().get_html()
+ if data != "":
+ return data
else:
# This should no longer be called on production now that we are using a separate updates page
# and using a fragment HTML file - it will be called in tests until those are removed.
diff --git a/common/lib/xmodule/xmodule/tests/test_html_module.py b/common/lib/xmodule/xmodule/tests/test_html_module.py
index a023a9072e..4176c0943d 100644
--- a/common/lib/xmodule/xmodule/tests/test_html_module.py
+++ b/common/lib/xmodule/xmodule/tests/test_html_module.py
@@ -5,7 +5,7 @@ import unittest
import ddt
from django.test.utils import override_settings
from mock import Mock
-from opaque_keys.edx.locator import CourseLocator
+from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
from xblock.field_data import DictFieldData
from xblock.fields import ScopeIds
@@ -98,13 +98,31 @@ class HtmlBlockCourseApiTestCase(unittest.TestCase):
class HtmlBlockSubstitutionTestCase(unittest.TestCase):
- def test_substitution_works(self):
+ def test_substitution_user_id(self):
sample_xml = '''%%USER_ID%%'''
field_data = DictFieldData({'data': sample_xml})
module_system = get_test_system()
module = HtmlBlock(module_system, field_data, Mock())
self.assertEqual(module.get_html(), str(module_system.anonymous_student_id))
+ def test_substitution_course_id(self):
+ sample_xml = '''%%COURSE_ID%%'''
+ field_data = DictFieldData({'data': sample_xml})
+ module_system = get_test_system()
+ module = HtmlBlock(module_system, field_data, Mock())
+ course_key = CourseLocator(
+ org='some_org',
+ course='some_course',
+ run='some_run'
+ )
+ usage_key = BlockUsageLocator(
+ course_key=course_key,
+ block_type='problem',
+ block_id='block_id'
+ )
+ module.scope_ids.usage_id = usage_key
+ self.assertEqual(module.get_html(), str(course_key))
+
def test_substitution_without_magic_string(self):
sample_xml = '''