from static_replace import replace_static_urls from xmodule.modulestore.exceptions import ItemNotFoundError def get_module_info(store, location, rewrite_static_links=False): try: module = store.get_item(location) except ItemNotFoundError: # create a new one store.create_and_save_xmodule(location) module = store.get_item(location) data = module.data if rewrite_static_links: # we pass a partially bogus course_id as we don't have the RUN information passed yet # through the CMS. Also the contentstore is also not RUN-aware at this point in time. data = replace_static_urls( module.data, None, course_id=module.location.org + '/' + module.location.course + '/BOGUS_RUN_REPLACE_WHEN_AVAILABLE' ) return { 'id': module.location.url(), 'data': data, # TODO (cpennington): This really shouldn't have to do this much reaching in to get the metadata # what's the intent here? all metadata incl inherited & namespaced? 'metadata': module.xblock_kvs._metadata } def set_module_info(store, location, post_data): module = None try: module = store.get_item(location) except ItemNotFoundError: # new module at this location: almost always used for the course about pages; thus, no parent. (there # are quite a handful of about page types available for a course and only the overview is pre-created) store.create_and_save_xmodule(location) module = store.get_item(location) if post_data.get('data') is not None: data = post_data['data'] store.update_item(location, data) # cdodge: note calling request.POST.get('children') will return None if children is an empty array # so it lead to a bug whereby the last component to be deleted in the UI was not actually # deleting the children object from the children collection if 'children' in post_data and post_data['children'] is not None: children = post_data['children'] store.update_children(location, children) # cdodge: also commit any metadata which might have been passed along in the # POST from the client, if it is there # NOTE, that the postback is not the complete metadata, as there's system metadata which is # not presented to the end-user for editing. So let's fetch the original and # 'apply' the submitted metadata, so we don't end up deleting system metadata if post_data.get('metadata') is not None: posted_metadata = post_data['metadata'] # update existing metadata with submitted metadata (which can be partial) # IMPORTANT NOTE: if the client passed pack 'null' (None) for a piece of metadata that means 'remove it' for metadata_key, value in posted_metadata.items(): if posted_metadata[metadata_key] is None: # remove both from passed in collection as well as the collection read in from the modulestore if module._field_data.has(module, metadata_key): module._field_data.delete(module, metadata_key) del posted_metadata[metadata_key] else: module._field_data.set(module, metadata_key, value) # commit to datastore # TODO (cpennington): This really shouldn't have to do this much reaching in to get the metadata store.update_metadata(location, module.xblock_kvs._metadata)