Ejemplo n.º 1
0
def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=False, include_child_info=False,
                       course_outline=False, include_children_predicate=NEVER, parent_xblock=None, graders=None,
                       user=None, course=None):
    """
    Creates the information needed for client-side XBlockInfo.

    If data or metadata are not specified, their information will not be added
    (regardless of whether or not the xblock actually has data or metadata).

    There are three optional boolean parameters:
      include_ancestor_info - if true, ancestor info is added to the response
      include_child_info - if true, direct child info is included in the response
      course_outline - if true, the xblock is being rendered on behalf of the course outline.
        There are certain expensive computations that do not need to be included in this case.

    In addition, an optional include_children_predicate argument can be provided to define whether or
    not a particular xblock should have its children included.
    """
    is_library_block = isinstance(xblock.location, LibraryUsageLocator)
    is_xblock_unit = is_unit(xblock, parent_xblock)
    # this should not be calculated for Sections and Subsections on Unit page or for library blocks
    has_changes = None
    if (is_xblock_unit or course_outline) and not is_library_block:
        has_changes = modulestore().has_changes(xblock)

    if graders is None:
        if not is_library_block:
            graders = CourseGradingModel.fetch(xblock.location.course_key).graders
        else:
            graders = []

    # Filter the graders data as needed
    graders = _filter_entrance_exam_grader(graders)

    # We need to load the course in order to retrieve user partition information.
    # For this reason, we load the course once and re-use it when recursively loading children.
    if course is None:
        course = modulestore().get_course(xblock.location.course_key)

    # Compute the child info first so it can be included in aggregate information for the parent
    should_visit_children = include_child_info and (course_outline and not is_xblock_unit or not course_outline)
    if should_visit_children and xblock.has_children:
        child_info = _create_xblock_child_info(
            xblock,
            course_outline,
            graders,
            include_children_predicate=include_children_predicate,
            user=user,
            course=course
        )
    else:
        child_info = None

    release_date = _get_release_date(xblock, user)

    if xblock.category != 'course':
        visibility_state = _compute_visibility_state(xblock, child_info, is_xblock_unit and has_changes)
    else:
        visibility_state = None
    published = modulestore().has_published_version(xblock) if not is_library_block else None

    # defining the default value 'True' for delete, drag and add new child actions in xblock_actions for each xblock.
    xblock_actions = {'deletable': True, 'draggable': True, 'childAddable': True}
    explanatory_message = None

    # is_entrance_exam is inherited metadata.
    if xblock.category == 'chapter' and getattr(xblock, "is_entrance_exam", None):
        # Entrance exam section should not be deletable, draggable and not have 'New Subsection' button.
        xblock_actions['deletable'] = xblock_actions['childAddable'] = xblock_actions['draggable'] = False
        if parent_xblock is None:
            parent_xblock = get_parent_xblock(xblock)

        # Translators: The {pct_sign} here represents the percent sign, i.e., '%'
        # in many languages. This is used to avoid Transifex's misinterpreting of
        # '% o'. The percent sign is also translatable as a standalone string.
        explanatory_message = _('Students must score {score}{pct_sign} or higher to access course materials.').format(
            score=int(parent_xblock.entrance_exam_minimum_score_pct * 100),
            # Translators: This is the percent sign. It will be used to represent
            # a percent value out of 100, e.g. "58%" means "58/100".
            pct_sign=_('%'))

    xblock_info = {
        "id": unicode(xblock.location),
        "display_name": xblock.display_name_with_default,
        "category": xblock.category,
        "edited_on": get_default_time_display(xblock.subtree_edited_on) if xblock.subtree_edited_on else None,
        "published": published,
        "published_on": get_default_time_display(xblock.published_on) if published and xblock.published_on else None,
        "studio_url": xblock_studio_url(xblock, parent_xblock),
        "released_to_students": datetime.now(UTC) > xblock.start,
        "release_date": release_date,
        "visibility_state": visibility_state,
        "has_explicit_staff_lock": xblock.fields['visible_to_staff_only'].is_set_on(xblock),
        "start": xblock.fields['start'].to_json(xblock.start),
        "graded": xblock.graded,
        "due_date": get_default_time_display(xblock.due),
        "due": xblock.fields['due'].to_json(xblock.due),
        "format": xblock.format,
        "course_graders": [grader.get('type') for grader in graders],
        "has_changes": has_changes,
        "actions": xblock_actions,
        "explanatory_message": explanatory_message,
        "group_access": xblock.group_access,
        "user_partitions": get_user_partition_info(xblock, course=course),
    }

    # update xblock_info with special exam information if the feature flag is enabled
    if settings.FEATURES.get('ENABLE_SPECIAL_EXAMS'):
        if xblock.category == 'course':
            xblock_info.update({
                "enable_proctored_exams": xblock.enable_proctored_exams,
                "enable_timed_exams": xblock.enable_timed_exams
            })
        elif xblock.category == 'sequential':
            xblock_info.update({
                "is_proctored_exam": xblock.is_proctored_exam,
                "is_practice_exam": xblock.is_practice_exam,
                "is_time_limited": xblock.is_time_limited,
                "default_time_limit_minutes": xblock.default_time_limit_minutes
            })

    # Entrance exam subsection should be hidden. in_entrance_exam is inherited metadata, all children will have it.
    if xblock.category == 'sequential' and getattr(xblock, "in_entrance_exam", False):
        xblock_info["is_header_visible"] = False

    if data is not None:
        xblock_info["data"] = data
    if metadata is not None:
        xblock_info["metadata"] = metadata
    if include_ancestor_info:
        xblock_info['ancestor_info'] = _create_xblock_ancestor_info(xblock, course_outline)
    if child_info:
        xblock_info['child_info'] = child_info
    if visibility_state == VisibilityState.staff_only:
        xblock_info["ancestor_has_staff_lock"] = ancestor_has_staff_lock(xblock, parent_xblock)
    else:
        xblock_info["ancestor_has_staff_lock"] = False

    if course_outline:
        if xblock_info["has_explicit_staff_lock"]:
            xblock_info["staff_only_message"] = True
        elif child_info and child_info["children"]:
            xblock_info["staff_only_message"] = all([child["staff_only_message"] for child in child_info["children"]])
        else:
            xblock_info["staff_only_message"] = False

    return xblock_info
Ejemplo n.º 2
0
 def _get_partition_info(self, schemes=None):
     """Retrieve partition info and selected groups. """
     return utils.get_user_partition_info(self.block, schemes=schemes)
Ejemplo n.º 3
0
 def _get_partition_info(self, schemes=None):
     """Retrieve partition info and selected groups. """
     return utils.get_user_partition_info(self.block, schemes=schemes)