Skip to content

Commit

Permalink
refactor: remove XBlockSerializerForLearningCore
Browse files Browse the repository at this point in the history
The XBlockSerializerForLearningCore class existed to account for the
differences in how Blockstore and later Learning Core stored OLX. This
involved doing things like:

* removing the url_name attribute (because it's encoded elsewhere)
* special case conversion from <vertical> tags to <unit>
* other handling over child definition identifiers

Stripping the url_name was moved to the XBlockSerializer superclass
because it was useful for copy-paste functionality. The other two are no
longer relevant because Learning Core won't internally model a Unit as
an XBlock, and the Learning Core XBlock Runtime doesn't support having
children.
  • Loading branch information
ormsbee committed Oct 21, 2024
1 parent 96768c6 commit e61af3e
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 76 deletions.
4 changes: 2 additions & 2 deletions openedx/core/lib/xblock_serializer/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Public python API for serializing XBlocks to OLX
"""
# pylint: disable=unused-import
from .block_serializer import StaticFile, XBlockSerializer, XBlockSerializerForLearningCore
from .block_serializer import StaticFile, XBlockSerializer


def serialize_xblock_to_olx(block):
Expand Down Expand Up @@ -32,4 +32,4 @@ def serialize_modulestore_block_for_learning_core(block):
we have around how we should rewrite this (e.g. are we going to
remove <xblock-include>?).
"""
return XBlockSerializerForLearningCore(block)
return XBlockSerializer(block, write_url_name=False)
74 changes: 0 additions & 74 deletions openedx/core/lib/xblock_serializer/block_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,77 +158,3 @@ def _serialize_html_block(self, block) -> etree.Element:
escaped_block_data = block.data.replace("]]>", "]]&gt;")
olx_node.text = etree.CDATA(escaped_block_data)
return olx_node


class XBlockSerializerForLearningCore(XBlockSerializer):
"""
This class will serialize an XBlock, producing:
(1) A new definition ID for use in Learning Core
(2) an XML string defining the XBlock and referencing the IDs of its
children using <xblock-include /> syntax (which doesn't actually
contain the OLX of its children, just refers to them, so you have to
separately serialize them.)
(3) a list of any static files required by the XBlock and their URL
"""

def __init__(self, block, *args, **kwargs):
"""
Serialize an XBlock to an OLX string + supporting files, and store the
resulting data in this object.
"""
super().__init__(block, *args, **kwargs)
self.def_id = utils.learning_core_def_key_from_modulestore_usage_key(self.orig_block_key)

def _serialize_block(self, block) -> etree.Element:
""" Serialize an XBlock to OLX/XML. """
olx_node = super()._serialize_block(block)
# Apply some transformations to the OLX:
self._transform_olx(olx_node, usage_id=block.scope_ids.usage_id)
return olx_node

def _serialize_children(self, block, parent_olx_node):
"""
Recursively serialize the children of XBlock 'block'.
Subclasses may override this.
"""
for child_id in block.children:
# In modulestore, the "definition key" is a MongoDB ObjectID
# kept in split's definitions table, which theoretically allows
# the same block to be used in many places (each with a unique
# usage key). However, that functionality is not exposed in
# Studio (other than via content libraries). So when we import
# into Learning Core, we assume that each usage is unique, don't
# generate a usage key, and create a new "definition key" from
# the original usage key.
# So modulestore usage key
# block-v1:A+B+C+type@html+block@introduction
# will become Learning Core definition key
# html+introduction
#
# If we needed the real definition key, we could get it via
# child = block.runtime.get_block(child_id)
# child_def_id = str(child.scope_ids.def_id)
# and then use
# <xblock-include definition={child_def_id} usage={child_id.block_id} />
def_id = utils.learning_core_def_key_from_modulestore_usage_key(child_id)
parent_olx_node.append(parent_olx_node.makeelement("xblock-include", {"definition": def_id}))

def _transform_olx(self, olx_node, usage_id):
"""
Apply transformations to the given OLX etree Node.
"""
# Remove 'url_name' - we store the definition key in the folder name
# that holds the OLX and the usage key elsewhere, so specifying it
# within the OLX file is redundant and can lead to issues if the file is
# copied and pasted elsewhere in the bundle with a new definition key.
olx_node.attrib.pop('url_name', None)
# Convert <vertical> to the new <unit> tag/block
if olx_node.tag == 'vertical':
olx_node.tag = 'unit'
for key in olx_node.attrib.keys():
if key not in ('display_name', 'url_name'):
log.warning(
'<vertical> tag attribute "%s" will be ignored after conversion to <unit> (in %s)',
key,
str(usage_id)
)

0 comments on commit e61af3e

Please sign in to comment.