signals.py 3.29 KB
Newer Older
1
""" receivers of course_published and library_updated events in order to trigger indexing task """
2

3
import logging
4 5 6 7 8
from datetime import datetime
from pytz import UTC

from django.dispatch import receiver

9
from xmodule.modulestore.django import modulestore, SignalHandler
10
from contentstore.courseware_index import CoursewareSearchIndexer, LibrarySearchIndexer
11
from contentstore.proctoring import register_special_exams
12
from openedx.core.djangoapps.credit.signals import on_course_publish
13 14
from openedx.core.lib.gating import api as gating_api
from util.module_utils import yield_dynamic_descriptor_descendants
15 16


17 18 19
log = logging.getLogger(__name__)


20 21 22
@receiver(SignalHandler.course_published)
def listen_for_course_publish(sender, course_key, **kwargs):  # pylint: disable=unused-argument
    """
23 24 25
    Receives publishing signal and performs publishing related workflows, such as
    registering proctored exams, building up credit requirements, and performing
    search indexing
26
    """
27 28 29

    # first is to registered exams, the credit subsystem will assume that
    # all proctored exams have already been registered, so we have to do that first
30 31 32 33 34
    try:
        register_special_exams(course_key)
    # pylint: disable=broad-except
    except Exception as exception:
        log.exception(exception)
35 36 37 38 39 40 41 42

    # then call into the credit subsystem (in /openedx/djangoapps/credit)
    # to perform any 'on_publish' workflow
    on_course_publish(course_key)

    # Finally call into the course search subsystem
    # to kick off an indexing action

43
    if CoursewareSearchIndexer.indexing_is_enabled():
44 45 46
        # import here, because signal is registered at startup, but items in tasks are not yet able to be loaded
        from .tasks import update_search_index

47
        update_search_index.delay(unicode(course_key), datetime.now(UTC).isoformat())
48 49 50


@receiver(SignalHandler.library_updated)
51
def listen_for_library_update(sender, library_key, **kwargs):  # pylint: disable=unused-argument
52 53 54
    """
    Receives signal and kicks off celery task to update search index
    """
55

56
    if LibrarySearchIndexer.indexing_is_enabled():
57 58 59
        # import here, because signal is registered at startup, but items in tasks are not yet able to be loaded
        from .tasks import update_library_index

60
        update_library_index.delay(unicode(library_key), datetime.now(UTC).isoformat())
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87


@receiver(SignalHandler.item_deleted)
def handle_item_deleted(**kwargs):
    """
    Receives the item_deleted signal sent by Studio when an XBlock is removed from
    the course structure and removes any gating milestone data associated with it or
    its descendants.

    Arguments:
        kwargs (dict): Contains the content usage key of the item deleted

    Returns:
        None
    """

    usage_key = kwargs.get('usage_key')
    if usage_key:
        # Strip branch info
        usage_key = usage_key.for_branch(None)
        course_key = usage_key.course_key
        deleted_module = modulestore().get_item(usage_key)
        for module in yield_dynamic_descriptor_descendants(deleted_module, kwargs.get('user_id')):
            # Remove prerequisite milestone data
            gating_api.remove_prerequisite(module.location)
            # Remove any 'requires' course content milestone relationships
            gating_api.set_required_content(course_key, module.location, None, None)