Commit eca523e0 by Nimisha Asthagiri

Mobile API MA-7: Support A/B test and cohorted content

parent 091d6aeb
...@@ -9,9 +9,17 @@ def yield_dynamic_descriptor_descendents(descriptor, module_creator): # pylint: ...@@ -9,9 +9,17 @@ def yield_dynamic_descriptor_descendents(descriptor, module_creator): # pylint:
has dynamic children, the module will be created using module_creator has dynamic children, the module will be created using module_creator
and the children (as descriptors) of that module will be returned. and the children (as descriptors) of that module will be returned.
""" """
def get_dynamic_descriptor_children(descriptor): stack = [descriptor]
while len(stack) > 0:
next_descriptor = stack.pop()
stack.extend(get_dynamic_descriptor_children(next_descriptor, module_creator))
yield next_descriptor
def get_dynamic_descriptor_children(descriptor, module_creator, usage_key_filter=None):
""" """
Internal recursive helper for traversing the child hierarchy Returns the children of the given descriptor, while supporting descriptors with dynamic children.
""" """
module_children = [] module_children = []
if descriptor.has_dynamic_children(): if descriptor.has_dynamic_children():
...@@ -19,12 +27,5 @@ def yield_dynamic_descriptor_descendents(descriptor, module_creator): # pylint: ...@@ -19,12 +27,5 @@ def yield_dynamic_descriptor_descendents(descriptor, module_creator): # pylint:
if module is not None: if module is not None:
module_children = module.get_child_descriptors() module_children = module.get_child_descriptors()
else: else:
module_children = descriptor.get_children() module_children = descriptor.get_children(usage_key_filter)
return module_children return module_children
stack = [descriptor]
while len(stack) > 0:
next_descriptor = stack.pop()
stack.extend(get_dynamic_descriptor_children(next_descriptor))
yield next_descriptor
...@@ -408,7 +408,7 @@ class XModuleMixin(XBlockMixin): ...@@ -408,7 +408,7 @@ class XModuleMixin(XBlockMixin):
else: else:
return [self.display_name_with_default] return [self.display_name_with_default]
def get_children(self, usage_key_filter=lambda location: True): def get_children(self, usage_key_filter=None):
"""Returns a list of XBlock instances for the children of """Returns a list of XBlock instances for the children of
this module""" this module"""
...@@ -419,7 +419,7 @@ class XModuleMixin(XBlockMixin): ...@@ -419,7 +419,7 @@ class XModuleMixin(XBlockMixin):
self._child_instances = [] # pylint: disable=attribute-defined-outside-init self._child_instances = [] # pylint: disable=attribute-defined-outside-init
for child_loc in self.children: for child_loc in self.children:
# Skip if it doesn't satisfy the filter function # Skip if it doesn't satisfy the filter function
if not usage_key_filter(child_loc): if usage_key_filter and not usage_key_filter(child_loc):
continue continue
try: try:
child = self.runtime.get_block(child_loc) child = self.runtime.get_block(child_loc)
......
...@@ -5,6 +5,9 @@ from rest_framework.reverse import reverse ...@@ -5,6 +5,9 @@ from rest_framework.reverse import reverse
from xmodule.modulestore.mongo.base import BLOCK_TYPES_WITH_CHILDREN from xmodule.modulestore.mongo.base import BLOCK_TYPES_WITH_CHILDREN
from courseware.access import has_access from courseware.access import has_access
from courseware.model_data import FieldDataCache
from courseware.module_render import get_module_for_descriptor
from util.module_utils import get_dynamic_descriptor_children
from edxval.api import ( from edxval.api import (
get_video_info_for_course_and_profile, ValInternalError get_video_info_for_course_and_profile, ValInternalError
...@@ -39,6 +42,17 @@ class BlockOutline(object): ...@@ -39,6 +42,17 @@ class BlockOutline(object):
usage_key.block_type in BLOCK_TYPES_WITH_CHILDREN usage_key.block_type in BLOCK_TYPES_WITH_CHILDREN
) )
def create_module(descriptor):
"""
Factory method for creating and binding a module for the given descriptor.
"""
field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
self.course_id, self.request.user, descriptor
)
return get_module_for_descriptor(
self.request.user, self.request, descriptor, field_data_cache, self.course_id
)
child_to_parent = {} child_to_parent = {}
stack = [self.start_block] stack = [self.start_block]
while stack: while stack:
...@@ -49,7 +63,7 @@ class BlockOutline(object): ...@@ -49,7 +63,7 @@ class BlockOutline(object):
# the hierarchy. The reason being is that these blocks may not have human-readable names # the hierarchy. The reason being is that these blocks may not have human-readable names
# to display on the mobile clients. # to display on the mobile clients.
# Eventually, we'll need to figure out how we want these blocks to be displayed on the # Eventually, we'll need to figure out how we want these blocks to be displayed on the
# mobile clients. As, they are still accessible in the browser, just not navigatable # mobile clients. As they are still accessible in the browser, just not navigatable
# from the table-of-contents. # from the table-of-contents.
continue continue
...@@ -70,7 +84,11 @@ class BlockOutline(object): ...@@ -70,7 +84,11 @@ class BlockOutline(object):
} }
if curr_block.has_children: if curr_block.has_children:
children = curr_block.get_children(usage_key_filter=parent_or_requested_block_type) children = get_dynamic_descriptor_children(
curr_block,
create_module,
usage_key_filter=parent_or_requested_block_type
)
for block in reversed(children): for block in reversed(children):
stack.append(block) stack.append(block)
child_to_parent[block] = curr_block child_to_parent[block] = curr_block
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment