Skip to content

Commit 675fbbd

Browse files
committed
chore: add bind_for_student in LTI XBlock
1 parent b821ee2 commit 675fbbd

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

xblocks_contrib/lti/lti.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
from web_fragments.fragment import Fragment
7676
from webob import Response
7777
from xblock.core import List, Scope, String, XBlock
78-
from xblock.fields import Boolean, Float
78+
from xblock.fields import Boolean, Float, UserScope
7979

8080
try:
8181
from xblock.utils.resources import ResourceLoader
@@ -1043,3 +1043,56 @@ def definition_to_xml(self, resource_fs):
10431043
if self.data:
10441044
return etree.fromstring(self.data)
10451045
return etree.Element(self.category)
1046+
1047+
def bind_for_student(self, user_id, wrappers=None):
1048+
"""
1049+
Set up this XBlock to act as an XModule instead of an XModuleDescriptor.
1050+
1051+
Arguments:
1052+
user_id: The user_id to set in scope_ids
1053+
wrappers: These are a list functions that put a wrapper, such as
1054+
LmsFieldData or OverrideFieldData, around the field_data.
1055+
Note that the functions will be applied in the order in
1056+
which they're listed. So [f1, f2] -> f2(f1(field_data))
1057+
"""
1058+
1059+
# Skip rebinding if we're already bound a user, and it's this user.
1060+
if self.scope_ids.user_id is not None and user_id == self.scope_ids.user_id:
1061+
if getattr(self.runtime, "position", None):
1062+
# update the position of the tab
1063+
self.position = self.runtime.position # pylint: disable=attribute-defined-outside-init
1064+
return
1065+
1066+
# # If we are switching users mid-request, save the data from the old user.
1067+
# self.save()
1068+
1069+
# Update scope_ids to point to the new user.
1070+
self.scope_ids = self.scope_ids._replace(user_id=user_id)
1071+
1072+
# Clear out any cached instantiated children.
1073+
self.clear_child_cache()
1074+
1075+
# Clear out any cached field data scoped to the old user.
1076+
for field in self.fields.values():
1077+
if field.scope in (Scope.parent, Scope.children):
1078+
continue
1079+
1080+
if field.scope.user == UserScope.ONE:
1081+
field._del_cached_value(self) # pylint: disable=protected-access
1082+
# not the most elegant way of doing this, but if we're removing
1083+
# a field from the module's field_data_cache, we should also
1084+
# remove it from its _dirty_fields
1085+
if field in self._dirty_fields:
1086+
del self._dirty_fields[field]
1087+
1088+
if wrappers:
1089+
# Put user-specific wrappers around the field-data service for this block.
1090+
# Note that these are different from modulestore.xblock_field_data_wrappers, which are not user-specific.
1091+
wrapped_field_data = self.runtime.service(self, "field-data-unbound")
1092+
for wrapper in wrappers:
1093+
wrapped_field_data = wrapper(wrapped_field_data)
1094+
self._bound_field_data = wrapped_field_data # pylint: disable=attribute-defined-outside-init
1095+
if getattr(self.runtime, "uses_deprecated_field_data", False):
1096+
# This approach is deprecated but old mongo's CachingDescriptorSystem still requires it.
1097+
# For Split mongo's CachingDescriptor system, don't set ._field_data this way.
1098+
self._field_data = wrapped_field_data

0 commit comments

Comments
 (0)