def _publish_events(cls, block_structure, location, previous_count, max_count, block_keys): """ Helper method to publish events for analytics purposes """ def format_block_keys(keys): """ Helper function to format block keys """ json_result = [] for key in keys: info = block_structure.get_transformer_block_field( key, ContentLibraryTransformer, 'block_analytics_summary' ) json_result.append(info) return json_result def publish_event(event_name, result, **kwargs): """ Helper function to publish an event for analytics purposes """ event_data = { "location": unicode(location), "previous_count": previous_count, "result": result, "max_count": max_count } event_data.update(kwargs) tracker.emit("edx.librarycontentblock.content.{}".format(event_name), event_data) LibraryContentModule.publish_selected_children_events( block_keys, format_block_keys, publish_event, )
def transform(self, usage_info, block_structure): """ Mutates block_structure based on the given usage_info. """ all_library_children = set() all_selected_children = set() for block_key in block_structure.topological_traversal( filter_func=lambda block_key: block_key.block_type == 'library_content', yield_descendants_of_unyielded=True, ): library_children = block_structure.get_children(block_key) if library_children: all_library_children.update(library_children) selected = [] mode = block_structure.get_xblock_field(block_key, 'mode') max_count = block_structure.get_xblock_field(block_key, 'max_count') # Retrieve "selected" json from LMS MySQL database. module = self._get_student_module(usage_info.user, usage_info.course_key, block_key) if module: state_dict = json.loads(module.state) # Add all selected entries for this user for this # library module to the selected list. for state in state_dict['selected']: usage_key = usage_info.course_key.make_usage_key(state[0], state[1]) if usage_key in library_children: selected.append((state[0], state[1])) # update selected previous_count = len(selected) block_keys = LibraryContentModule.make_selection(selected, library_children, max_count, mode) selected = block_keys['selected'] # publish events for analytics self._publish_events(block_structure, block_key, previous_count, max_count, block_keys) all_selected_children.update(usage_info.course_key.make_usage_key(s[0], s[1]) for s in selected) def check_child_removal(block_key): """ Return True if selected block should be removed. Block is removed if it is part of library_content, but has not been selected for current user. """ if block_key not in all_library_children: return False if block_key in all_selected_children: return False return True # Check and remove all non-selected children from course # structure. block_structure.remove_block_if( check_child_removal )
def transform_block_filters(self, usage_info, block_structure): all_library_children = set() all_selected_children = set() for block_key in block_structure: if block_key.block_type != 'library_content': continue library_children = block_structure.get_children(block_key) if library_children: all_library_children.update(library_children) selected = [] mode = block_structure.get_xblock_field(block_key, 'mode') max_count = block_structure.get_xblock_field( block_key, 'max_count') # Retrieve "selected" json from LMS MySQL database. module = self._get_student_module(usage_info.user, usage_info.course_key, block_key) if module: state_dict = json.loads(module.state) # Add all selected entries for this user for this # library module to the selected list. for state in state_dict['selected']: usage_key = usage_info.course_key.make_usage_key( state[0], state[1]) if usage_key in library_children: selected.append((state[0], state[1])) # update selected previous_count = len(selected) block_keys = LibraryContentModule.make_selection( selected, library_children, max_count, mode) selected = block_keys['selected'] # publish events for analytics self._publish_events(block_structure, block_key, previous_count, max_count, block_keys) all_selected_children.update( usage_info.course_key.make_usage_key(s[0], s[1]) for s in selected) def check_child_removal(block_key): """ Return True if selected block should be removed. Block is removed if it is part of library_content, but has not been selected for current user. """ if block_key not in all_library_children: return False if block_key in all_selected_children: return False return True return [block_structure.create_removal_filter(check_child_removal)]
def _publish_events(self, block_structure, location, previous_count, max_count, block_keys, user_id): """ Helper method to publish events for analytics purposes """ def format_block_keys(keys): """ Helper function to format block keys """ json_result = [] for key in keys: info = block_structure.get_transformer_block_field( key, ContentLibraryTransformer, 'block_analytics_summary') json_result.append(info) return json_result def publish_event(event_name, result, **kwargs): """ Helper function to publish an event for analytics purposes """ event_data = { "location": six.text_type(location), "previous_count": previous_count, "result": result, "max_count": max_count, } event_data.update(kwargs) context = contexts.course_context_from_course_id( location.course_key) if user_id: context['user_id'] = user_id full_event_name = "edx.librarycontentblock.content.{}".format( event_name) with tracker.get_tracker().context(full_event_name, context): tracker.emit(full_event_name, event_data) LibraryContentModule.publish_selected_children_events( block_keys, format_block_keys, publish_event, )
def _publish_events(self, block_structure, location, previous_count, max_count, block_keys, user_id): """ Helper method to publish events for analytics purposes """ def format_block_keys(keys): """ Helper function to format block keys """ json_result = [] for key in keys: info = block_structure.get_transformer_block_field( key, ContentLibraryTransformer, 'block_analytics_summary' ) json_result.append(info) return json_result def publish_event(event_name, result, **kwargs): """ Helper function to publish an event for analytics purposes """ event_data = { "location": unicode(location), "previous_count": previous_count, "result": result, "max_count": max_count, } event_data.update(kwargs) context = contexts.course_context_from_course_id(location.course_key) if user_id: context['user_id'] = user_id full_event_name = "edx.librarycontentblock.content.{}".format(event_name) with tracker.get_tracker().context(full_event_name, context): tracker.emit(full_event_name, event_data) LibraryContentModule.publish_selected_children_events( block_keys, format_block_keys, publish_event, )
def transform_block_filters(self, usage_info, block_structure): all_library_children = set() all_selected_children = set() for block_key in block_structure: if block_key.block_type != 'library_content': continue library_children = block_structure.get_children(block_key) if library_children: all_library_children.update(library_children) selected = [] mode = block_structure.get_xblock_field(block_key, 'mode') max_count = block_structure.get_xblock_field(block_key, 'max_count') # Retrieve "selected" json from LMS MySQL database. module = self._get_student_module(usage_info.user, usage_info.course_key, block_key) if module: state_dict = json.loads(module.state) # Add all selected entries for this user for this # library module to the selected list. for state in state_dict['selected']: usage_key = usage_info.course_key.make_usage_key(state[0], state[1]) if usage_key in library_children: selected.append((state[0], state[1])) # update selected previous_count = len(selected) block_keys = LibraryContentModule.make_selection(selected, library_children, max_count, mode) selected = block_keys['selected'] # publish events for analytics self._publish_events(block_structure, block_key, previous_count, max_count, block_keys) all_selected_children.update(usage_info.course_key.make_usage_key(s[0], s[1]) for s in selected) def check_child_removal(block_key): """ Return True if selected block should be removed. Block is removed if it is part of library_content, but has not been selected for current user. """ if block_key not in all_library_children: return False if block_key in all_selected_children: return False return True return [block_structure.create_removal_filter(check_child_removal)]
def transform_block_filters(self, usage_info, block_structure): all_library_children = set() all_selected_children = set() for block_key in block_structure: if block_key.block_type != 'library_content': continue library_children = block_structure.get_children(block_key) if library_children: all_library_children.update(library_children) selected = [] mode = block_structure.get_xblock_field(block_key, 'mode') max_count = block_structure.get_xblock_field( block_key, 'max_count') # Retrieve "selected" json from LMS MySQL database. state_dict = get_student_module_as_dict( usage_info.user, usage_info.course_key, block_key) for selected_block in state_dict.get('selected', []): # Add all selected entries for this user for this # library module to the selected list. block_type, block_id = selected_block usage_key = usage_info.course_key.make_usage_key( block_type, block_id) if usage_key in library_children: selected.append(selected_block) # Update selected previous_count = len(selected) block_keys = LibraryContentModule.make_selection( selected, library_children, max_count, mode) selected = block_keys['selected'] # Save back any changes if any(block_keys[changed] for changed in ('invalid', 'overlimit', 'added')): state_dict['selected'] = list(selected) StudentModule.save_state( student=usage_info.user, course_id=usage_info.course_key, module_state_key=block_key, defaults={ 'state': json.dumps(state_dict), }, ) # publish events for analytics self._publish_events( block_structure, block_key, previous_count, max_count, block_keys, usage_info.user.id, ) all_selected_children.update( usage_info.course_key.make_usage_key(s[0], s[1]) for s in selected) def check_child_removal(block_key): """ Return True if selected block should be removed. Block is removed if it is part of library_content, but has not been selected for current user, with staff as an exemption. """ if usage_info.has_staff_access: return False if block_key not in all_library_children: return False if block_key in all_selected_children: return False return True return [block_structure.create_removal_filter(check_child_removal)]
def transform_block_filters(self, usage_info, block_structure): all_library_children = set() all_selected_children = set() for block_key in block_structure: if block_key.block_type != 'library_content': continue library_children = block_structure.get_children(block_key) if library_children: all_library_children.update(library_children) selected = [] mode = block_structure.get_xblock_field(block_key, 'mode') max_count = block_structure.get_xblock_field(block_key, 'max_count') # Retrieve "selected" json from LMS MySQL database. module = self._get_student_module(usage_info.user, usage_info.course_key, block_key) if module: state_dict = json.loads(module.state) else: state_dict = {} for selected_block in state_dict.get('selected', []): # Add all selected entries for this user for this # library module to the selected list. block_type, block_id = selected_block usage_key = usage_info.course_key.make_usage_key(block_type, block_id) if usage_key in library_children: selected.append(selected_block) # Update selected previous_count = len(selected) block_keys = LibraryContentModule.make_selection(selected, library_children, max_count, mode) selected = block_keys['selected'] # Save back any changes if any(block_keys[changed] for changed in ('invalid', 'overlimit', 'added')): state_dict['selected'] = list(selected) StudentModule.objects.update_or_create( # pylint: disable=no-member student=usage_info.user, course_id=usage_info.course_key, module_state_key=block_key, defaults={ 'state': json.dumps(state_dict), }, ) # publish events for analytics self._publish_events(block_structure, block_key, previous_count, max_count, block_keys) all_selected_children.update(usage_info.course_key.make_usage_key(s[0], s[1]) for s in selected) def check_child_removal(block_key): """ Return True if selected block should be removed. Block is removed if it is part of library_content, but has not been selected for current user. """ if block_key not in all_library_children: return False if block_key in all_selected_children: return False return True return [block_structure.create_removal_filter(check_child_removal)]