Source code for timApp.document.create_item

from typing import Generator, Union, Optional

from timApp.auth.accesshelper import (
    grant_access_to_session_users,
    reset_request_access_cache,
    get_doc_or_abort,
    verify_edit_access,
)
from timApp.auth.sessioninfo import (
    get_current_user_object,
    get_current_user_group_object,
)
from timApp.bookmark.bookmarks import LAST_EDITED_GROUP
from timApp.document.docentry import DocEntry, get_documents, create_document_and_block
from timApp.document.docinfo import DocInfo
from timApp.document.documents import apply_citation
from timApp.document.exceptions import ValidationException
from timApp.document.specialnames import (
    FORCED_TEMPLATE_NAME,
    TEMPLATE_FOLDER_NAME,
    PREAMBLE_FOLDER_NAME,
)
from timApp.document.translation.translation import Translation, add_tr_entry
from timApp.folder.folder import Folder
from timApp.item.block import copy_default_rights, BlockType
from timApp.item.tag import TagType, Tag
from timApp.item.validation import (
    validate_item_and_create_intermediate_folders,
    ItemValidationRule,
)
from timApp.tim_app import app
from timApp.user.usergroup import UserGroup
from timApp.user.userutils import DOC_DEFAULT_RIGHT_NAME, FOLDER_DEFAULT_RIGHT_NAME
from timApp.util.flask.requesthelper import RouteException
from timApp.util.utils import split_location


[docs]def get_templates_for_folder(folder: Folder) -> list[DocEntry]: current_path = folder.path templates = [] u = get_current_user_object() while True: for t in get_documents( filter_folder=current_path + "/" + TEMPLATE_FOLDER_NAME, search_recursively=False, filter_user=u, ): if t.short_name not in (DOC_DEFAULT_RIGHT_NAME, FOLDER_DEFAULT_RIGHT_NAME): templates.append(t) if current_path == "": break current_path, short_name = split_location(current_path) # Templates should not be templates of templates themselves. We skip them. # TODO Think if this needs a while loop in case of path like templates/templates/templates if short_name == TEMPLATE_FOLDER_NAME: current_path, short_name = split_location(current_path) templates.sort(key=lambda d: d.short_name.lower()) return templates
[docs]def create_document( item_path: str, item_title: str, validation_rule: ItemValidationRule = None, parent_owner: UserGroup = None, doc_owner: UserGroup | None = None, ) -> DocInfo: return do_create_item( item_path, BlockType.Document, item_title, validation_rule, parent_owner, doc_owner, )
[docs]def do_create_item( item_path: str, item_type: BlockType, item_title: str, validation_rule: ItemValidationRule = None, parent_owner: UserGroup = None, doc_owner: UserGroup | None = None, ) -> DocInfo | Folder: create_function = ( DocEntry.create if item_type == BlockType.Document else Folder.create ) owner_group = doc_owner if doc_owner else get_current_user_group_object() item_path = item_path.strip("/") validate_item_and_create_intermediate_folders( item_path, item_type, parent_owner or owner_group, validation_rule ) item = create_function(item_path, owner_group, item_title) grant_access_to_session_users(item) if item_type == BlockType.Document and app.config["BOOKMARKS_ENABLED"]: bms = get_current_user_object().bookmarks bms.add_bookmark( LAST_EDITED_GROUP, item.title, item.url_relative, move_to_top=True, limit=app.config["LAST_EDITED_BOOKMARK_LIMIT"], ).save_bookmarks() copy_default_rights(item, item_type) reset_request_access_cache() return item
[docs]def apply_template(item: DocInfo, template_name: str | None = None): templates = get_templates_for_folder(item.parent) matched_templates = None if template_name: matched_templates = list( filter(lambda t: t.short_name == template_name, templates) ) if not matched_templates: matched_templates = list( filter(lambda t: t.short_name == FORCED_TEMPLATE_NAME, templates) ) if matched_templates: template = matched_templates[0] item.document.update( template.document.export_markdown(), item.document.export_markdown() )
[docs]def copy_document_and_enum_translations( source: DocInfo, target: DocInfo, copy_uploads: bool ) -> Generator[tuple[DocInfo, DocInfo], None, None]: is_preamble = f"/{TEMPLATE_FOLDER_NAME}/{PREAMBLE_FOLDER_NAME}/" in source.path if copy_uploads: target.children.extend( source.children ) # required to retain rights to uploaded files # Copy tags except course code and subject. for tag in source.block.tags: if tag.type == TagType.Regular: target.block.tags.append( Tag(name=tag.name, type=tag.type, expires=tag.expires) ) try: target.document.update( source.document.export_markdown(), target.document.export_markdown(), strict_validation=False, regenerate_ids=is_preamble, ) except ValidationException as e: raise ValidationException( f"Could not copy {source.path} because it contains an error: {e}" ) for tr in source.translations: # type: Translation doc_id = target.id new_tr = None if not tr.is_original_translation: document = create_document_and_block( get_current_user_object().get_personal_group() ) doc_id = document.doc_id new_tr = add_tr_entry(doc_id, target, tr) document.docinfo = new_tr document.update( tr.document.export_markdown(), document.export_markdown(), strict_validation=False, regenerate_ids=is_preamble, ) elif tr.lang_id: add_tr_entry(doc_id, target, tr) if not tr.is_original_translation: yield tr, new_tr
[docs]def create_or_copy_item( item_path: str, item_type: BlockType, item_title: str, copy_id: int | None = None, template_name: str | None = None, use_template: bool = True, copy_uploads: bool = True, ): d = None if copy_id: d = get_doc_or_abort(copy_id) verify_edit_access(d) d = d.src_doc vr = d.document.validate() if vr.issues: raise RouteException( f"The following errors must be fixed before copying:\n{vr}" ) item = do_create_item(item_path, item_type, item_title) if isinstance(item, DocInfo): if d: for tr, new_tr in copy_document_and_enum_translations( d, item, copy_uploads=copy_uploads ): copy_default_rights(new_tr, BlockType.Document) elif use_template: apply_template(item, template_name) return item
[docs]def create_citation_doc(doc_id: int, doc_path: str, doc_title: str): d = get_doc_or_abort(doc_id) verify_edit_access(d) src_doc = d.document item = create_document(doc_path, doc_title) apply_citation(item, src_doc) return item