def get_library(library_key): """ Get the library with the specified key. Does not check permissions. returns a ContentLibraryMetadata instance. Raises ContentLibraryNotFound if the library doesn't exist. """ assert isinstance(library_key, LibraryLocatorV2) ref = ContentLibrary.objects.get_by_key(library_key) bundle_metadata = get_bundle(ref.bundle_uuid) lib_bundle = LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME) num_blocks = len(lib_bundle.get_top_level_usages()) last_published = lib_bundle.get_last_published_time() (has_unpublished_changes, has_unpublished_deletes) = lib_bundle.has_changes() return ContentLibraryMetadata( key=library_key, bundle_uuid=ref.bundle_uuid, title=bundle_metadata.title, description=bundle_metadata.description, num_blocks=num_blocks, version=bundle_metadata.latest_version, last_published=last_published, allow_public_learning=ref.allow_public_learning, allow_public_read=ref.allow_public_read, has_unpublished_changes=has_unpublished_changes, has_unpublished_deletes=has_unpublished_deletes, )
def get_item_definition(cls, item): ref = ContentLibrary.objects.get_by_key(item) lib_bundle = LibraryBundle(item, ref.bundle_uuid, draft_name=DRAFT_NAME) num_blocks = len(lib_bundle.get_top_level_usages()) last_published = lib_bundle.get_last_published_time() last_published_str = None if last_published: last_published_str = last_published.strftime('%Y-%m-%dT%H:%M:%SZ') (has_unpublished_changes, has_unpublished_deletes) = lib_bundle.has_changes() bundle_metadata = get_bundle(ref.bundle_uuid) # NOTE: Increment ContentLibraryIndexer.SCHEMA_VERSION if the following schema is updated to avoid dealing # with outdated indexes which might cause errors due to missing/invalid attributes. return { "schema_version": ContentLibraryIndexer.SCHEMA_VERSION, "id": str(item), "uuid": str(bundle_metadata.uuid), "title": bundle_metadata.title, "description": bundle_metadata.description, "num_blocks": num_blocks, "version": bundle_metadata.latest_version, "last_published": last_published_str, "has_unpublished_changes": has_unpublished_changes, "has_unpublished_deletes": has_unpublished_deletes, # only 'content' field is analyzed by elastisearch, and allows text-search "content": { "id": str(item), "title": bundle_metadata.title, "description": bundle_metadata.description, }, }
def index_libraries(cls, library_keys): """ Index the specified libraries. If they already exist, replace them with new ones. """ searcher = SearchEngine.get_search_engine(cls.INDEX_NAME) library_dicts = [] for library_key in library_keys: ref = ContentLibrary.objects.get_by_key(library_key) lib_bundle = LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME) num_blocks = len(lib_bundle.get_top_level_usages()) last_published = lib_bundle.get_last_published_time() last_published_str = None if last_published: last_published_str = last_published.strftime( '%Y-%m-%dT%H:%M:%SZ') (has_unpublished_changes, has_unpublished_deletes) = lib_bundle.has_changes() bundle_metadata = get_bundle(ref.bundle_uuid) # NOTE: Increment ContentLibraryIndexer.SCHEMA_VERSION if the following schema is updated to avoid dealing # with outdated indexes which might cause errors due to missing/invalid attributes. library_dict = { "schema_version": ContentLibraryIndexer.SCHEMA_VERSION, "id": str(library_key), "uuid": str(bundle_metadata.uuid), "title": bundle_metadata.title, "description": bundle_metadata.description, "num_blocks": num_blocks, "version": bundle_metadata.latest_version, "last_published": last_published_str, "has_unpublished_changes": has_unpublished_changes, "has_unpublished_deletes": has_unpublished_deletes, } library_dicts.append(library_dict) return searcher.index(cls.LIBRARY_DOCUMENT_TYPE, library_dicts)
def get_library(library_key): """ Get the library with the specified key. Does not check permissions. returns a ContentLibraryMetadata instance. Raises ContentLibraryNotFound if the library doesn't exist. """ assert isinstance(library_key, LibraryLocatorV2) ref = ContentLibrary.objects.get_by_key(library_key) bundle_metadata = get_bundle(ref.bundle_uuid) lib_bundle = LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME) (has_unpublished_changes, has_unpublished_deletes) = lib_bundle.has_changes() return ContentLibraryMetadata( key=library_key, bundle_uuid=ref.bundle_uuid, title=bundle_metadata.title, description=bundle_metadata.description, version=bundle_metadata.latest_version, has_unpublished_changes=has_unpublished_changes, has_unpublished_deletes=has_unpublished_deletes, )
def update_library( library_key, title=None, description=None, allow_public_learning=None, allow_public_read=None, library_type=None, library_license=None, ): """ Update a library's metadata (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 not in (COMPLEX, ref.type): lib_bundle = LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME) (has_unpublished_changes, has_unpublished_deletes) = lib_bundle.has_changes() if has_unpublished_changes or has_unpublished_deletes: raise IncompatibleTypesError( _('You may not change a library\'s type to {library_type} if it still has unpublished changes.' ).format(library_type=library_type)) 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 library_license is not None: ref.license = library_license 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, str) fields["title"] = title if description is not None: assert isinstance(description, str) fields["description"] = description update_bundle(ref.bundle_uuid, **fields) CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=ref.library_key)