def _get_course_module(course_descriptor, user): """ Gets course module that takes into account user state and permissions """ # Adding courseware imports here to insulate other apps (e.g. schedules) to # avoid import errors. from lms.djangoapps.courseware.model_data import FieldDataCache from lms.djangoapps.courseware.module_render import get_module_for_descriptor # Fake a request to fool parts of the courseware that want to inspect it. request = get_request_or_stub() request.user = user # Now evil modulestore magic to inflate our descriptor with user state and # permissions checks. field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_descriptor.id, user, course_descriptor, depth=1, read_only=True, ) course_module = get_module_for_descriptor( user, request, course_descriptor, field_data_cache, course_descriptor.id, course=course_descriptor, ) if not course_module: raise CourseUpdateDoesNotExist('Course module {} not found'.format( course_descriptor.id)) return course_module
def test_repeated_course_module_instantiation(self, loops, course_depth): with modulestore().default_store(ModuleStoreEnum.Type.split): course = CourseFactory.create() chapter = ItemFactory(parent=course, category='chapter', graded=True) section = ItemFactory(parent=chapter, category='sequential') __ = ItemFactory(parent=section, category='problem') fake_request = self.factory.get( reverse('progress', kwargs={'course_id': str(course.id)})) course = modulestore().get_course(course.id, depth=course_depth) for _ in range(loops): field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, self.user, course, depth=course_depth) course_module = get_module_for_descriptor(self.user, fake_request, course, field_data_cache, course.id, course=course) for chapter in course_module.get_children(): for section in chapter.get_children(): for item in section.get_children(): assert item.graded
def _update_last_visited_module_id(self, request, course, module_key, modification_date): """ Saves the module id if the found modification_date is less recent than the passed modification date """ field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, request.user, course, depth=2) try: module_descriptor = modulestore().get_item(module_key) except ItemNotFoundError: return Response(errors.ERROR_INVALID_MODULE_ID, status=400) module = get_module_for_descriptor( request.user, request, module_descriptor, field_data_cache, course.id, course=course ) if modification_date: key = KeyValueStore.Key( scope=Scope.user_state, user_id=request.user.id, block_scope_id=course.location, field_name='position' ) original_store_date = field_data_cache.last_modified(key) if original_store_date is not None and modification_date < original_store_date: # old modification date so skip update return self._get_course_info(request, course) save_positions_recursively_up(request.user, request, field_data_cache, module, course=course) return self._get_course_info(request, course)
def edxnotes_visibility(request, course_id): """ Handle ajax call from "Show notes" checkbox. """ course_key = CourseKey.from_string(course_id) course = get_course_with_access(request.user, "load", course_key) field_data_cache = FieldDataCache([course], course_key, request.user) course_module = get_module_for_descriptor(request.user, request, course, field_data_cache, course_key, course=course) if not is_feature_enabled(course, request.user): raise Http404 try: visibility = json.loads(request.body.decode('utf8'))["visibility"] course_module.edxnotes_visibility = visibility course_module.save() return JsonResponse(status=200) except (ValueError, KeyError): log.warning( u"Could not decode request body as JSON and find a boolean visibility field: '%s'", request.body) return JsonResponseBadRequest()
def _get_course_module(course_descriptor, user): # Adding courseware imports here to insulate other apps (e.g. schedules) to # avoid import errors. from lms.djangoapps.courseware.model_data import FieldDataCache from lms.djangoapps.courseware.module_render import get_module_for_descriptor # Fake a request to fool parts of the courseware that want to inspect it. request = get_request_or_stub() request.user = user # Now evil modulestore magic to inflate our descriptor with user state and # permissions checks. field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_descriptor.id, user, course_descriptor, depth=1, read_only=True, ) return get_module_for_descriptor( user, request, course_descriptor, field_data_cache, course_descriptor.id, course=course_descriptor, )
def _last_visited_module_path(self, request, course): """ Returns the path from the last module visited by the current user in the given course up to the course module. If there is no such visit, the first item deep enough down the course tree is used. """ field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, request.user, course, depth=2) course_module = get_module_for_descriptor(request.user, request, course, field_data_cache, course.id, course=course) path = [course_module] chapter = get_current_child(course_module, min_depth=2) if chapter is not None: path.append(chapter) section = get_current_child(chapter, min_depth=1) if section is not None: path.append(section) path.reverse() return path
def get_course_child_content(request, user, course_key, child_descriptor): """ Returns course child content """ field_data_cache = FieldDataCache([child_descriptor], course_key, user) child_content = module_render.get_module_for_descriptor( user, request, child_descriptor, field_data_cache, course_key) return child_content
def get_course_content(request, user, course_key, course_descriptor): # pylint: disable=W0613 """ Returns course content """ field_data_cache = FieldDataCache([course_descriptor], course_key, user) course_content = module_render.get_module_for_descriptor( user, request, course_descriptor, field_data_cache, course_key) return course_content
def _get_course_module(course_descriptor, user): # Fake a request to fool parts of the courseware that want to inspect it. request = get_request_or_stub() request.user = user # Now evil modulestore magic to inflate our descriptor with user state and # permissions checks. field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_descriptor.id, user, course_descriptor, depth=1, read_only=True, ) return get_module_for_descriptor( user, request, course_descriptor, field_data_cache, course_descriptor.id, course=course_descriptor, )
def test_changing_position_works(self): # Make a mock FieldDataCache for this course, so we can get the course module mock_field_data_cache = FieldDataCache([self.course], self.course.id, self.student) course = get_module_for_descriptor(self.student, MagicMock(name='request'), self.course, mock_field_data_cache, self.course.id, course=self.course) # Now that we have the course, change the position and save, nothing should explode! course.position = 2 course.save()
def edxnotes(request, course_id): """ Displays the EdxNotes page. Arguments: request: HTTP request object course_id: course id Returns: Rendered HTTP response. """ course_key = CourseKey.from_string(course_id) course = get_course_with_access(request.user, "load", course_key) if not is_feature_enabled(course, request.user): raise Http404 notes_info = get_notes(request, course) has_notes = (len(notes_info.get('results')) > 0) context = { "course": course, "notes_endpoint": reverse("notes", kwargs={"course_id": course_id}), "notes": notes_info, "page_size": DEFAULT_PAGE_SIZE, "debug": settings.DEBUG, 'position': None, 'disabled_tabs': settings.NOTES_DISABLED_TABS, 'has_notes': has_notes, } if not has_notes: field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, request.user, course, depth=2) course_module = get_module_for_descriptor(request.user, request, course, field_data_cache, course_key, course=course) position = get_course_position(course_module) if position: context.update({ 'position': position, }) return render_to_response("edxnotes/edxnotes.html", context)
def complete_student_attempt_task(user_identifier: str, content_id: str) -> None: """ Marks all completable children of content_id as complete for the user Submits all completable xblocks inside of the content_id block to the Completion Service to mark them as complete. One use case of this function is for special exams (timed/proctored) where regardless of submission status on individual problems, we want to mark the entire exam as complete when the exam is finished. params: user_identifier (str): username or email of a user content_id (str): the block key for a piece of content """ err_msg_prefix = ( 'Error occurred while attempting to complete student attempt for user ' f'{user_identifier} for content_id {content_id}. ' ) err_msg = None try: user = get_user_by_username_or_email(user_identifier) block_key = UsageKey.from_string(content_id) root_descriptor = modulestore().get_item(block_key) except ObjectDoesNotExist: err_msg = err_msg_prefix + 'User does not exist!' except InvalidKeyError: err_msg = err_msg_prefix + 'Invalid content_id!' except ItemNotFoundError: err_msg = err_msg_prefix + 'Block not found in the modulestore!' if err_msg: log.error(err_msg) return # This logic has been copied over from openedx/core/djangoapps/schedules/content_highlights.py # in the _get_course_module function. # I'm not sure if this is an anti-pattern or not, so if you can avoid re-copying this, please do. # We are using it here because we ran into issues with the User service being undefined when we # encountered a split_test xblock. # Fake a request to fool parts of the courseware that want to inspect it. request = get_request_or_stub() request.user = user # Now evil modulestore magic to inflate our descriptor with user state and # permissions checks. field_data_cache = FieldDataCache.cache_for_descriptor_descendents( root_descriptor.course_id, user, root_descriptor, read_only=True, ) root_module = get_module_for_descriptor( user, request, root_descriptor, field_data_cache, root_descriptor.course_id, ) if not root_module: err_msg = err_msg_prefix + 'Module unable to be created from descriptor!' log.error(err_msg) return def _submit_completions(block, user): """ Recursively submits the children for completion to the Completion Service """ mode = XBlockCompletionMode.get_mode(block) if mode == XBlockCompletionMode.COMPLETABLE: block.runtime.publish(block, 'completion', {'completion': 1.0, 'user_id': user.id}) elif mode == XBlockCompletionMode.AGGREGATOR: # I know this looks weird, but at the time of writing at least, there isn't a good # single way to get the children assigned for a partcular user. Some blocks define the # child descriptors method, but others don't and with blocks like Randomized Content # (Library Content), the get_children method returns all children and not just assigned # children. So this is our way around situations like that. See also Split Test Module # for another use case where user state has to be taken into account via get_child_descriptors block_children = ((hasattr(block, 'get_child_descriptors') and block.get_child_descriptors()) or (hasattr(block, 'get_children') and block.get_children()) or []) for child in block_children: _submit_completions(child, user) _submit_completions(root_module, user)