|
| 1 | +"""Signal handlers for writing course dates into edx_when.""" |
| 2 | +from __future__ import absolute_import, unicode_literals |
| 3 | + |
| 4 | +import logging |
| 5 | + |
| 6 | +from django.dispatch import receiver |
| 7 | +from six import text_type |
| 8 | +from xblock.fields import Scope |
| 9 | +from xmodule.modulestore.django import SignalHandler, modulestore |
| 10 | + |
| 11 | +from edx_when.api import FIELDS_TO_EXTRACT, set_dates_for_course |
| 12 | + |
| 13 | +log = logging.getLogger(__name__) |
| 14 | + |
| 15 | + |
| 16 | +def date_field_values(date_fields, xblock): |
| 17 | + """ |
| 18 | + Read field values for the specified date fields from the supplied xblock. |
| 19 | + """ |
| 20 | + result = {} |
| 21 | + for field_name in date_fields: |
| 22 | + if field_name not in xblock.fields: |
| 23 | + continue |
| 24 | + field = xblock.fields[field_name] |
| 25 | + if field.scope == Scope.settings and field.is_set_on(xblock): |
| 26 | + try: |
| 27 | + result[field.name] = field.read_from(xblock) |
| 28 | + except TypeError as exception: |
| 29 | + exception_message = "{message}, Block-location:{location}, Field-name:{field_name}".format( |
| 30 | + message=text_type(exception), |
| 31 | + location=text_type(xblock.location), |
| 32 | + field_name=field.name |
| 33 | + ) |
| 34 | + raise TypeError(exception_message) |
| 35 | + return result |
| 36 | + |
| 37 | + |
| 38 | +def extract_dates_from_course(course): |
| 39 | + """ |
| 40 | + Extract all dates from the supplied course. |
| 41 | + """ |
| 42 | + log.info('Publishing course dates for %s', course.id) |
| 43 | + if course.self_paced: |
| 44 | + metadata = date_field_values(FIELDS_TO_EXTRACT, course) |
| 45 | + # self-paced courses may accidentally have a course due date |
| 46 | + metadata.pop('due', None) |
| 47 | + date_items = [(course.location, metadata)] |
| 48 | + else: |
| 49 | + date_items = [] |
| 50 | + items = modulestore().get_items(course.id) |
| 51 | + log.info('extracting dates from %d items in %s', len(items), course.id) |
| 52 | + for item in items: |
| 53 | + date_items.append((item.location, date_field_values(FIELDS_TO_EXTRACT, item))) |
| 54 | + return date_items |
| 55 | + |
| 56 | + |
| 57 | +@receiver(SignalHandler.course_published) |
| 58 | +def extract_dates(sender, course_key, **kwargs): # pylint: disable=unused-argument |
| 59 | + """ |
| 60 | + Extract dates from blocks when publishing a course. |
| 61 | + """ |
| 62 | + log.info("Extracting dates from %s", course_key) |
| 63 | + |
| 64 | + course = modulestore().get_course(course_key) |
| 65 | + |
| 66 | + if not course: |
| 67 | + log.info("No course found for key %s", course_key) |
| 68 | + return |
| 69 | + |
| 70 | + date_items = extract_dates_from_course(course) |
| 71 | + |
| 72 | + try: |
| 73 | + set_dates_for_course(course_key, date_items) |
| 74 | + except Exception: # pylint: disable=broad-except |
| 75 | + log.exception('setting dates for %s', course_key) |
0 commit comments