def create_bundle_link(library_key, link_id, target_opaque_key, version=None): """ Create a new link to the resource with the specified opaque key. For now, only LibraryLocatorV2 opaque keys are supported. """ ref = ContentLibrary.objects.get_by_key(library_key) # Make sure this link ID/name is not already in use: links = blockstore_cache.get_bundle_draft_direct_links_cached( ref.bundle_uuid, DRAFT_NAME) if link_id in links: raise InvalidNameError("That link ID is already in use.") # Determine the target: if not isinstance(target_opaque_key, LibraryLocatorV2): raise TypeError( "For now, only LibraryLocatorV2 opaque keys are supported by create_bundle_link" ) target_bundle_uuid = ContentLibrary.objects.get_by_key( target_opaque_key).bundle_uuid if version is None: version = get_bundle(target_bundle_uuid).latest_version # Create the new link: draft = get_or_create_bundle_draft(ref.bundle_uuid, DRAFT_NAME) set_draft_link(draft.uuid, link_id, target_bundle_uuid, version) # Clear the cache: LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear() CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=library_key)
def update_library( library_key, title=None, description=None, allow_public_learning=None, allow_public_read=None, library_type=None, ): """ Update a library's title or description. (Slug cannot be changed as it would break IDs throughout the system.) A value of None means "don't change". """ ref = ContentLibrary.objects.get_by_key(library_key) # Update MySQL model: changed = False if allow_public_learning is not None: ref.allow_public_learning = allow_public_learning changed = True if allow_public_read is not None: ref.allow_public_read = allow_public_read changed = True if library_type is not None: if library_type != COMPLEX: for block in get_library_blocks(library_key): if block.usage_key.block_type != library_type: raise IncompatibleTypesError( _('You can only set a library to {library_type} if all existing blocks are of that type. ' 'Found incompatible block {block_id} with type {block_type}.' ).format( library_type=library_type, block_type=block.usage_key.block_type, block_id=block.usage_key.block_id, ), ) ref.type = library_type changed = True if changed: ref.save() # Update Blockstore: fields = { # We don't ever read the "slug" value from the Blockstore bundle, but # we might as well always do our best to keep it in sync with the "slug" # value in the LMS that we do use. "slug": ref.slug, } if title is not None: assert isinstance(title, six.string_types) fields["title"] = title if description is not None: assert isinstance(description, six.string_types) fields["description"] = description update_bundle(ref.bundle_uuid, **fields) CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=ref.library_key)
def revert_changes(library_key): """ Revert all pending changes to the specified library, restoring it to the last published version. """ ref = ContentLibrary.objects.get_by_key(library_key) bundle = get_bundle(ref.bundle_uuid) if DRAFT_NAME in bundle.drafts: # pylint: disable=unsupported-membership-test draft_uuid = bundle.drafts[DRAFT_NAME] # pylint: disable=unsubscriptable-object delete_draft(draft_uuid) else: return # If there is no draft, no action is needed. LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear() CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=library_key, update_blocks=True)
def publish_changes(library_key): """ Publish all pending changes to the specified library. """ ref = ContentLibrary.objects.get_by_key(library_key) bundle = get_bundle(ref.bundle_uuid) if DRAFT_NAME in bundle.drafts: # pylint: disable=unsupported-membership-test draft_uuid = bundle.drafts[DRAFT_NAME] # pylint: disable=unsubscriptable-object commit_draft(draft_uuid) else: return # If there is no draft, no action is needed. LibraryBundle(library_key, ref.bundle_uuid).cache.clear() LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear() CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=library_key)
def update_library( library_key, title=None, description=None, allow_public_learning=None, allow_public_read=None, ): """ Update a library's title or description. (Slug cannot be changed as it would break IDs throughout the system.) A value of None means "don't change". """ ref = ContentLibrary.objects.get_by_key(library_key) # Update MySQL model: changed = False if allow_public_learning is not None: ref.allow_public_learning = allow_public_learning changed = True if allow_public_read is not None: ref.allow_public_read = allow_public_read changed = True if changed: ref.save() # Update Blockstore: fields = { # We don't ever read the "slug" value from the Blockstore bundle, but # we might as well always do our best to keep it in sync with the "slug" # value in the LMS that we do use. "slug": ref.slug, } if title is not None: assert isinstance(title, six.string_types) fields["title"] = title if description is not None: assert isinstance(description, six.string_types) fields["description"] = description update_bundle(ref.bundle_uuid, **fields) CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=ref.library_key)
def update_bundle_link(library_key, link_id, version=None, delete=False): """ Update a bundle's link to point to the specified version of its target bundle. Use version=None to automatically point to the latest version. Use delete=True to delete the link. """ ref = ContentLibrary.objects.get_by_key(library_key) draft = get_or_create_bundle_draft(ref.bundle_uuid, DRAFT_NAME) if delete: set_draft_link(draft.uuid, link_id, None, None) else: links = blockstore_cache.get_bundle_draft_direct_links_cached(ref.bundle_uuid, DRAFT_NAME) try: link = links[link_id] except KeyError: raise InvalidNameError("That link does not exist.") if version is None: version = get_bundle(link.bundle_uuid).latest_version set_draft_link(draft.uuid, link_id, link.bundle_uuid, version) # Clear the cache: LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear() CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=library_key)