示例#1
0
    def check_children_for_content_type_gating_paywall(self, item, course_id):
        """
        Arguments:
            item (xblock such as a sequence or vertical block)
            course_id (CourseLocator)

        If:
            This xblock contains problems which this user cannot load due to content type gating
        Then:
            Return the first content type gating paywall (Fragment)
        Else:
            Return None
        """
        user = self._get_user()
        if not user:
            return None

        if not self._enabled_for_enrollment(user=user, course_key=course_id):
            return None

        # Check children for content type gated content
        for block in traverse_pre_order(item, get_children, leaf_filter):
            gate_fragment = self._content_type_gate_for_block(
                user, block, course_id)
            if gate_fragment is not None:
                return gate_fragment.content

        return None
示例#2
0
    def _check_children_for_content_type_gating_paywall(self, item):
        """
        If:
        This xblock contains problems which this user cannot load due to content type gating
        Then:
        Return the first content type gating paywall (Fragment)
        Else:
        Return None
        """
        try:
            user = self._get_user()
            course_id = self.runtime.course_id
            content_type_gating_service = self.runtime.service(
                self, 'content_type_gating')
            if not (content_type_gating_service
                    and content_type_gating_service.enabled_for_enrollment(
                        user=user, course_key=course_id)):
                return None

            for block in traverse_pre_order(item, get_children, leaf_filter):
                gate_fragment = content_type_gating_service.content_type_gate_for_block(
                    user, block, course_id)
                if gate_fragment is not None:
                    return gate_fragment.content
        except get_user_model().DoesNotExist:
            pass
        return None
示例#3
0
def _has_assignment_blocks(item):
    """
    Check if a given block contains children that are assignments.
    Assignments have graded, has_score and nonzero weight attributes.
    """
    return any(
        is_xblock_an_assignment(block)
        for block in traverse_pre_order(item, get_children, leaf_filter))
示例#4
0
    def _get_leaf_blocks(cls, unit):  # lint-amnesty, pylint: disable=missing-function-docstring
        def leaf_filter(block):
            return (
                block.location.block_type not in ('chapter', 'sequential', 'vertical') and
                len(cls._get_children(block)) == 0
            )

        return list(traverse_pre_order(unit, cls._get_visible_children, leaf_filter))
    def _get_leaf_blocks(cls, unit):
        def leaf_filter(block):
            return (block.location.block_type
                    not in ('chapter', 'sequential', 'vertical')
                    and len(cls._get_children(block)) == 0)

        return [
            block for block in traverse_pre_order(
                unit, cls._get_visible_children, leaf_filter)
        ]
示例#6
0
    def _get_leaf_blocks(cls, unit):
        def leaf_filter(block):
            return (
                block.location.block_type not in ('chapter', 'sequential', 'vertical') and
                len(cls._get_children(block)) == 0
            )

        return [
            block for block in
            traverse_pre_order(unit, cls._get_visible_children, leaf_filter)
        ]
示例#7
0
    def gate_sequence_if_it_is_a_timed_exam_and_contains_content_type_gated_problems(
            self):
        """
        Problem:
        Content type gating for FBE (Feature Based Enrollments) previously only gated individual blocks.
        This was an issue because audit learners could start a timed exam
        and then be unable to complete it because the graded content would be gated.
        Even if they later upgraded, they could still be unable to complete the exam
        because the timer could have expired.

        Solution:
        Gate the entire sequence when we think the above problem can occur.

        If:
        1. This sequence is a timed exam
        2. And this sequence contains problems which this user cannot load due to content type gating
        Then:
        We will gate access to the entire sequence.
        Otherwise, learners would have the ability to start their timer for an exam,
        but then not have the ability to complete it.

        We are displaying the gating fragment within the sequence, as is done for gating for prereqs,
        rather than content type gating the entire sequence because that would remove the next/previous navigation.

        When gated_sequence_fragment is not set to None, the sequence will be gated.

        This functionality still needs to be replicated in the frontend-app-learning courseware MFE
        The ticket to track this is https://openedx.atlassian.net/browse/REV-1220
        Note that this will break compatability with using sequences outside of edx-platform
        but we are ok with this for now
        """
        if not self.is_time_limited:
            self.gated_sequence_fragment = None
            return

        try:
            user = self._get_user()
            course_id = self.runtime.course_id
            content_type_gating_service = self.runtime.service(
                self, 'content_type_gating')
            if not (content_type_gating_service
                    and content_type_gating_service.enabled_for_enrollment(
                        user=user, course_key=course_id)):
                self.gated_sequence_fragment = None
                return

            def leaf_filter(block):
                # This function is used to check if this is a leaf block
                # Blocks with children are not currently gated by content type gating
                # Other than the outer function here
                return (block.location.block_type
                        not in ('chapter', 'sequential', 'vertical')
                        and not block.has_children)

            def get_children(parent):
                # This function is used to get the children of a block in the traversal below
                if parent.has_children:
                    return parent.get_children()
                else:
                    return []

            # If any block inside a timed exam has been gated by content type gating
            # then gate the entire sequence.
            # In order to avoid scope creep, we are not handling other potential causes
            # of access failures as part of this work.
            for block in traverse_pre_order(self, get_children, leaf_filter):
                gate_fragment = content_type_gating_service.content_type_gate_for_block(
                    user, block, course_id)
                if gate_fragment is not None:
                    self.gated_sequence_fragment = gate_fragment
                    return
                else:
                    self.gated_sequence_fragment = None
        except User.DoesNotExist:
            self.gated_sequence_fragment = None