<reponame>osoco/better-ways-of-thinking-about-software
"""
Student View Transformer
"""


from openedx.core.djangoapps.content.block_structure.transformer import BlockStructureTransformer


class StudentViewTransformer(BlockStructureTransformer):
    """
    Only show information that is appropriate for a learner
    """
    WRITE_VERSION = 1
    READ_VERSION = 1
    STUDENT_VIEW_DATA = 'student_view_data'
    STUDENT_VIEW_MULTI_DEVICE = 'student_view_multi_device'

    def __init__(self, requested_student_view_data=None):
        self.requested_student_view_data = requested_student_view_data or []

    @classmethod
    def name(cls):
        return "blocks_api:student_view"

    @classmethod
    def collect(cls, block_structure):
        """
        Collect student_view_multi_device and student_view_data values for each block
        """
        # collect basic xblock fields
        block_structure.request_xblock_fields('category')

        for block_key in block_structure.topological_traversal():
            block = block_structure.get_xblock(block_key)

            # We're iterating through descriptors (not bound to a user) that are
            # given to us by the modulestore. The reason we look at
            # block.__class__ is to avoid the XModuleDescriptor -> XModule
            # proxying that would happen if we just examined block directly,
            # since it's likely that student_view() is going to be defined on
            # the XModule side.
            #
            # If that proxying happens, this method will throw an
            # UndefinedContext exception, because we haven't initialized any of
            # the user-specific context.
            #
            # This isn't a problem for pure XBlocks, because it's all in one
            # class, and there's no proxying. So basically, if you encounter a
            # problem where your particular XModule explodes here (and don't
            # have the time to convert it to an XBlock), please try refactoring
            # so that you declare your student_view() method in a common
            # ancestor class of both your Descriptor and Module classes.
            student_view = getattr(block.__class__, 'student_view', None)
            supports_multi_device = block.has_support(student_view, 'multi_device')

            block_structure.set_transformer_block_field(
                block_key,
                cls,
                cls.STUDENT_VIEW_MULTI_DEVICE,
                supports_multi_device,
            )
            if getattr(block, 'student_view_data', None):
                student_view_data = block.student_view_data()
                block_structure.set_transformer_block_field(
                    block_key,
                    cls,
                    cls.STUDENT_VIEW_DATA,
                    student_view_data,
                )

    def transform(self, usage_info, block_structure):
        """
        Mutates block_structure based on the given usage_info.
        """
        for block_key in block_structure.post_order_traversal():
            if block_structure.get_xblock_field(block_key, 'category') not in self.requested_student_view_data:
                block_structure.remove_transformer_block_field(block_key, self, self.STUDENT_VIEW_DATA)

"""
Student View Transformer
"""


from openedx.core.djangoapps.content.block_structure.transformer import BlockStructureTransformer


class StudentViewTransformer(BlockStructureTransformer):
    """
    Only show information that is appropriate for a learner
    """
    WRITE_VERSION = 1
    READ_VERSION = 1
    STUDENT_VIEW_DATA = 'student_view_data'
    STUDENT_VIEW_MULTI_DEVICE = 'student_view_multi_device'

    def __init__(self, requested_student_view_data=None):
        self.requested_student_view_data = requested_student_view_data or []

    @classmethod
    def name(cls):
        return "blocks_api:student_view"

    @classmethod
    def collect(cls, block_structure):
        """
        Collect student_view_multi_device and student_view_data values for each block
        """
        # collect basic xblock fields
        block_structure.request_xblock_fields('category')

        for block_key in block_structure.topological_traversal():
            block = block_structure.get_xblock(block_key)

            # We're iterating through descriptors (not bound to a user) that are
            # given to us by the modulestore. The reason we look at
            # block.__class__ is to avoid the XModuleDescriptor -> XModule
            # proxying that would happen if we just examined block directly,
            # since it's likely that student_view() is going to be defined on
            # the XModule side.
            #
            # If that proxying happens, this method will throw an
            # UndefinedContext exception, because we haven't initialized any of
            # the user-specific context.
            #
            # This isn't a problem for pure XBlocks, because it's all in one
            # class, and there's no proxying. So basically, if you encounter a
            # problem where your particular XModule explodes here (and don't
            # have the time to convert it to an XBlock), please try refactoring
            # so that you declare your student_view() method in a common
            # ancestor class of both your Descriptor and Module classes.
            student_view = getattr(block.__class__, 'student_view', None)
            supports_multi_device = block.has_support(student_view, 'multi_device')

            block_structure.set_transformer_block_field(
                block_key,
                cls,
                cls.STUDENT_VIEW_MULTI_DEVICE,
                supports_multi_device,
            )
            if getattr(block, 'student_view_data', None):
                student_view_data = block.student_view_data()
                block_structure.set_transformer_block_field(
                    block_key,
                    cls,
                    cls.STUDENT_VIEW_DATA,
                    student_view_data,
                )

    def transform(self, usage_info, block_structure):
        """
        Mutates block_structure based on the given usage_info.
        """
        for block_key in block_structure.post_order_traversal():
            if block_structure.get_xblock_field(block_key, 'category') not in self.requested_student_view_data:
                block_structure.remove_transformer_block_field(block_key, self, self.STUDENT_VIEW_DATA)
Student View Transformer Only show information that is appropriate for a learner Collect student_view_multi_device and student_view_data values for each block # collect basic xblock fields # We're iterating through descriptors (not bound to a user) that are # given to us by the modulestore. The reason we look at # block.__class__ is to avoid the XModuleDescriptor -> XModule # proxying that would happen if we just examined block directly, # since it's likely that student_view() is going to be defined on # the XModule side. # # If that proxying happens, this method will throw an # UndefinedContext exception, because we haven't initialized any of # the user-specific context. # # This isn't a problem for pure XBlocks, because it's all in one # class, and there's no proxying. So basically, if you encounter a # problem where your particular XModule explodes here (and don't # have the time to convert it to an XBlock), please try refactoring # so that you declare your student_view() method in a common # ancestor class of both your Descriptor and Module classes. Mutates block_structure based on the given usage_info.