course_metadata.py 2.61 KB
Newer Older
1 2
from xblock.fields import Scope

3
from contentstore.utils import get_modulestore
4
from cms.lib.xblock.mixin import CmsBlockMixin
5

Chris Dodge committed
6

7 8
class CourseMetadata(object):
    '''
9 10 11 12
    For CRUD operations on metadata fields which do not have specific editors
    on the other pages including any user generated ones.
    The objects have no predefined attrs but instead are obj encodings of the
    editable metadata.
13
    '''
cahrens committed
14 15 16 17 18 19 20
    FILTERED_LIST = ['xml_attributes',
                     'start',
                     'end',
                     'enrollment_start',
                     'enrollment_end',
                     'tabs',
                     'graceperiod',
21
                     'checklists',
22 23 24
                     'show_timezone',
                     'format',
                     'graded',
cahrens committed
25
    ]
26

27
    @classmethod
28
    def fetch(cls, descriptor):
29
        """
30 31
        Fetch the key:value editable course details for the given course from
        persistence and return a CourseMetadata model.
32
        """
33
        result = {}
34

Calen Pennington committed
35 36 37 38
        for field in descriptor.fields.values():
            if field.name in CmsBlockMixin.fields:
                continue

39 40 41
            if field.scope != Scope.settings:
                continue

Calen Pennington committed
42 43 44
            if field.name in cls.FILTERED_LIST:
                continue

45
            result[field.name] = field.read_json(descriptor)
46

47
        return result
48

49
    @classmethod
50
    def update_from_json(cls, descriptor, jsondict, filter_tabs=True, user=None):
51
        """
Don Mitchell committed
52
        Decode the json into CourseMetadata and save any changed attrs to the db.
53

Don Mitchell committed
54
        Ensures none of the fields are in the blacklist.
55 56
        """
        dirty = False
Chris Dodge committed
57

58 59 60
        # Copy the filtered list to avoid permanently changing the class attribute.
        filtered_list = list(cls.FILTERED_LIST)
        # Don't filter on the tab attribute if filter_tabs is False.
61 62 63
        if not filter_tabs:
            filtered_list.remove("tabs")

David Baumgold committed
64
        for key, val in jsondict.iteritems():
65
            # should it be an error if one of the filtered list items is in the payload?
David Baumgold committed
66
            if key in filtered_list:
67 68
                continue

69 70 71 72 73
            if key == "unsetKeys":
                dirty = True
                for unset in val:
                    descriptor.fields[unset].delete_from(descriptor)

David Baumgold committed
74
            if hasattr(descriptor, key) and getattr(descriptor, key) != val:
75
                dirty = True
Calen Pennington committed
76
                value = descriptor.fields[key].from_json(val)
David Baumgold committed
77
                setattr(descriptor, key, value)
78

79
        if dirty:
80
            get_modulestore(descriptor.location).update_item(descriptor, user.id if user else None)
81

82
        return cls.fetch(descriptor)