def delete_category(blog_id, category_id, confirm='N'): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) category = Category.load(category_id, blog_id=blog.id) auth.check_category_editing_lock(blog) tags = template_tags(blog=blog, user=user) from core.utils import Status if request.forms.getunicode('confirm') == user.logout_nonce: message = 'Category {} successfully deleted'.format(category.for_log) url = '{}/blog/{}/categories'.format(BASE_URL, blog.id) action = 'Return to the category listing' reparent_categories = Category.update( parent_category=category.parent_category).where( Category.parent_category == category) reparent_categories.execute() delete_category = PageCategory.delete().where( PageCategory.category == category.id) delete_category.execute() category.delete_instance() tags.status = Status(type='success', message=message, action=action, url=url, close=False) else: message = ( 'You are about to delete category <b>{}</b> from blog <b>{}</b>.'. format(category.for_display, blog.for_display)) yes = { 'label': 'Yes, delete this category', 'id': 'delete', 'name': 'confirm', 'value': user.logout_nonce } no = { 'label': 'No, return to category properties', 'url': '{}/blog/{}/category/{}'.format(BASE_URL, blog.id, category.id) } tags.status = Status(message=message, type='warning', close=False, yes=yes, no=no) tags.category = category return report(tags, 'blog_delete_category', category)
def blog_apply_theme(blog_id, theme_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) reason = auth.check_template_lock(blog) theme = Theme.load(theme_id) tags = template_tags(blog=blog, user=user) from core.utils import Status if request.forms.getunicode('confirm') == user.logout_nonce: from core.models import db with db.atomic() as txn: blog.apply_theme(theme, user) status = Status(type='success', close=False, message=''' Theme <b>{}</b> was successfully applied to blog <b>{}</b>.</p> It is recommended that you <a href="{}">republish this blog.</a> '''.format(theme.for_display, blog.for_display, '{}/blog/{}/republish'.format(BASE_URL, blog.id))) else: status = Status(type='warning', close=False, message=''' You are about to apply theme <b>{}</b> to blog <b>{}</b>.</p> <p>This will OVERWRITE AND REMOVE ALL EXISTING TEMPLATES on this blog!</p> '''.format(theme.for_display, blog.for_display), url='{}/blog/{}/themes'.format(BASE_URL, blog.id), yes={ 'id': 'delete', 'name': 'confirm', 'label': 'Yes, I want to apply this theme', 'value': user.logout_nonce }, no={ 'label': 'No, don\'t apply this theme', 'url': '{}/blog/{}/themes'.format(BASE_URL, blog.id) }) tags.status = status if reason is None else reason return report(tags, 'blog_apply_theme', [blog, theme])
def template_delete(template_id): ''' UI for deleting a template ''' user = auth.is_logged_in(request) tpl = Template.load(template_id) blog = Blog.load(tpl.blog) permission = auth.is_blog_designer(user, blog) from core.utils import Status import settings tags = template_tags(template_id=tpl.id, user=user) if request.forms.getunicode('confirm') == user.logout_nonce: # _template.delete(tpl) tpl.delete_instance() status = Status(type='success', close=False, message='Template {} was successfully deleted.'.format( tpl.for_log), action='Return to template list', url='{}/blog/{}/templates'.format( settings.BASE_URL, blog.id)) else: status = Status( type='warning', close=False, message= 'You are attempting to delete template <b>{}</b> from blog <b>{}</b>.' .format(tpl.for_display, blog.for_display), no={ 'url': '{}/template/{}/edit'.format(settings.BASE_URL, tpl.id), 'label': 'No, I don\'t want to delete this template' }, yes={ 'id': 'delete', 'name': 'confirm', 'label': 'Yes, I want to delete this template', 'value': user.logout_nonce }) tags.status = status return report(tags, 'blog_delete_template', tpl)
def queue_clear(blog_id): from core.ui.blog import blog_queue_clear, blog_queue blog_queue_clear(blog_id) from core.utils import Status status = Status( type='success', no_sure=True, message='Blog {}\'s queue has been successfully cleared.'.format( blog_id)) return blog_queue(blog_id, status)
def check_publishing_lock(blog, action_description, warn_only=False): ''' Checks for a publishing lock and returns a status message if busy. ''' try: publishing_lock(blog) except QueueInProgressException as e: msg = "{} is not available right now. Proceed with caution. Reason: {}".format( action_description, e) if warn_only is True: return Status(type='warning', message=msg) else: raise QueueInProgressException(msg)
def template_set_default(template_id): ''' UI for setting a given template as the default for an archive type ''' user = auth.is_logged_in(request) tpl = Template.load(template_id) blog = Blog.load(tpl.blog.id) permission = auth.is_blog_designer(user, blog) auth.check_template_lock(blog) tags = template_tags(template=tpl, user=user) from core.utils import Status import settings if request.forms.getunicode('confirm') == user.logout_nonce: # check for form submission # setting should be done by way of class object # theme? blog? template? # blog.set_default_archive_template(template,{archive_type.index...}) status = Status( type='success', close=False, message= 'Template <b>{}</b> was successfully refreshed from theme <b>{}</b>.' .format(tpl.for_display, tpl.theme.for_display), action='Return to template', url='{}/template/{}/edit'.format(settings.BASE_URL, tpl.id)) tags.status = status else: pass from core.models import archive_defaults return template('edit/template-set-default', icons=icons, search_context=(search_contexts['blog'], tags.blog), menu=generate_menu('blog_edit_template', tags.template), sidebar=sidebar.render_sidebar( panel_set='edit_template', publishing_mode=publishing_mode, types=template_type, **tags.__dict__), archive_defaults=archive_defaults, **tags.__dict__)
def blog_queue_run(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) import subprocess, sys taskpath = "{}/scripts/tasks.py".format(APPLICATION_PATH) pid = subprocess.Popen([sys.executable, taskpath, '--nowait']).pid msg = "<a href='../queue'>Queue</a> runner {} started with pid {}. ".format( taskpath, pid) from core.utils import Status status = Status(type='success', no_sure=True, message=msg) tags = template_tags(blog_id=blog.id, user=user, status=status) return report(tags, 'blog_menu', blog)
def blog_settings_save(request, blog, user): _forms = request.forms blog_name = _forms.getunicode('blog_name') if blog_name is not None: blog.name = blog_name blog_description = _forms.getunicode('blog_description') if blog_description is not None: blog.description = blog_description blog_url = _forms.getunicode('blog_url') if blog_url is not None: blog_url = blog_url.rstrip('/') blog.url = blog_url # TODO: url validation blog_path = _forms.getunicode('blog_path') if blog_path is not None: blog_path = blog_path.rstrip('/') blog.path = blog_path # TODO: validate this path blog_base_extension = _forms.getunicode('blog_base_extension') if blog_base_extension is not None: blog_base_extension = blog_base_extension.lstrip('.') blog.base_extension = blog_base_extension blog.save() status = Status(type='success', message="Settings for <b>{}</b> saved.", vals=(blog.name, )) logger.info("Settings for blog {} edited by user {}.".format( blog.for_log, user.for_log)) return status
def blog_delete_preview(blog_id, preview_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) f = lambda: None f.blog = blog if preview_id == 'all': previews_to_delete = blog.fileinfos.where( FileInfo.preview_path.is_null(False)) message = 'All previews for blog {} deleted.'.format(blog.for_display) f.msg = 'Delete all' else: previews_to_delete = blog.fileinfos.where(FileInfo.id == preview_id) message = 'Preview for fileinfo {} deleted.'.format(preview_id) f.msg = 'Delete preview {}'.format(preview_id) for n in previews_to_delete: if n.page is not None: n.page.delete_preview() else: n.template_mapping.template.delete_preview() tags = template_tags(blog_id=blog.id, user=user) from core.utils import Status tags.status = Status( type='success', message=message, close=False, ) return report(tags, 'blog_delete_preview', f)
def media_delete(blog_id, media_id, confirm='N'): user = auth.is_logged_in(request) blog = Blog.load(blog_id) is_member = auth.is_blog_member(user, blog) media = Media.load(media_id, blog) permission = auth.is_media_owner(user, media) tags = template_tags(blog=blog, media=media, user=user) # report_txt = [] from core.utils import Status if request.forms.getunicode('confirm') == user.logout_nonce: from os import remove try: remove(media.path) except: pass media.delete_instance(recursive=True, delete_nullable=True) confirmed = Struct() confirmed.message = 'Media {} successfully deleted'.format( media.for_log) confirmed.url = '{}/blog/{}/media'.format(BASE_URL, blog.id) confirmed.action = 'Return to the media listing' tags.status = Status(type='success', message=confirmed.message, action=confirmed.action, url=confirmed.url, close=False) else: s1 = ( 'You are about to delete media object <b>{}</b> from blog <b>{}</b>.' .format(media.for_display, blog.for_display)) # used_in = [] # # for n in media.pages: # used_in.append("<li>{}</li>".format(n.for_display)) media_page_count = media.pages.count() if media_page_count > 0: s2 = ''' <p><b>There are still <a target="_blank" href="{}/blog/{}/media/{}/pages">{} pages</a> associated with this tag.</b></p> <p>Deleting the object will remove it from these pages as well.</p> <p>Any references to these images in text will show as broken.</p> '''.format(BASE_URL, blog.id, media.id, media_page_count) else: s2 = ''' <p>This media object is not currently used in any pages.</p> <p>However, if it is linked directly in a page without a media reference, any such links will break.</p> ''' yes = { 'label': 'Yes, delete this media', 'id': 'delete', 'name': 'confirm', 'value': user.logout_nonce } no = { 'label': 'No, return to media properties', 'url': '../{}/edit'.format(media.id) } tags.status = Status(type='warning', close=False, message=s1 + '<hr>' + s2, yes=yes, no=no) tags.icons = icons return report(tags, 'blog_delete_media', media)
def blog_settings_save(blog_id, nav_setting): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) _get = request.forms.getunicode # this could also be normalized?: # blog.form_gets([list here]) # & you could always add custom fields after the fact blog.name = _get('blog_name', blog.name) blog.description = _get('blog_description', blog.description) blog.set_timezone = _get('blog_timezone') blog.url = _get('blog_url', blog.url) blog.path = _get('blog_path', blog.path) blog.base_extension = _get('blog_base_extension', blog.base_extension) blog.media_path = _get('blog_media_path', blog.media_path) from core.utils import Status from core.libs.peewee import IntegrityError errors = [] try: blog.validate() blog.save() except IntegrityError as e: from core.utils import field_error errors.append(field_error(e)) except Exception as e: errors.extend(e.args[0]) # We could condense this all to: # blog.validate_and_save() # and just have it return errors as a list? if len(errors) > 0: status = Status( type='danger', no_sure=True, message= 'Blog settings could not be saved due to the following problems:', message_list=errors) else: status = Status( type='success', message= "Settings for <b>{}</b> saved successfully.<hr/>It is recommended that you <a href='{}/blog/{}/purge'>republish this blog</a> immediately." .format(blog.for_display, BASE_URL, blog.id)) logger.info("Settings for blog {} edited by user {}.".format( blog.for_log, user.for_log)) tags = template_tags(user=user) tags.blog = blog tags.nav_default = nav_setting if status is not None: tags.status = status return blog_settings_output(tags)
def template_edit_save(template_id): ''' UI for saving a blog template ''' user = auth.is_logged_in(request) tpl = Template.load(template_id) blog = Blog.load(tpl.blog) permission = auth.is_blog_designer(user, blog) auth.check_template_lock(blog) from core.utils import Status from core.error import TemplateSaveException, PageNotChanged status = None save_mode = int(request.forms.getunicode('save', default="0")) if save_mode in (1, 2, 3): try: message = template_save(request, user, tpl, blog) except TemplateSaveException as e: status = Status(type='danger', no_sure=True, message="Error saving template <b>{}</b>:".format( tpl.for_display), message_list=(e, )) except PageNotChanged as e: status = Status(type='success', message="Template <b>{}</b> was unchanged.".format( tpl.for_display)) except Exception as e: raise e status = Status( type='warning', no_sure=True, message="Problem saving template <b>{}</b>: <br>".format( tpl.for_display), message_list=(e, )) else: tpl.delete_preview() status = Status( type='success', message="Template <b>{}</b> saved successfully. {}".format( tpl.for_display, message) # TODO: move messages into message lister ) tags = template_tags(template_id=template_id, user=user) tags.mappings = template_mapping_index[tpl.template_type] tags.status = status from core.models import (template_type as template_types) return template('edit/template_ajax', sidebar=sidebar.render_sidebar( panel_set='edit_template', publishing_mode=publishing_mode, types=template_types, **tags.__dict__), **tags.__dict__)
def blog_save_theme(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) reason = auth.check_template_lock(blog) tags = template_tags(blog=blog, user=user) from core.utils import Status, create_basename_core if request.method == 'POST': theme = Theme( title=request.forms.getunicode('theme_title'), description=request.forms.getunicode('theme_description'), json='') export = blog.export_theme(theme.title, theme.description, user) from settings import THEME_FILE_PATH # , _sep import os directory_name = create_basename_core(theme.title) dirs = [x[0] for x in os.walk(THEME_FILE_PATH)] dir_name_ext = 0 dir_name_full = directory_name while 1: if dir_name_full in dirs: dir_name_ext += 1 dir_name_full = directory_name + "-" + str(dir_name_ext) continue else: break dir_name_final = os.path.join(THEME_FILE_PATH, dir_name_full) os.makedirs(dir_name_final) theme.json = dir_name_full theme.save() Template.update(theme=theme).where(Template.blog == blog).execute() TemplateRevision.update(theme=theme).where( TemplateRevision.blog == blog).execute() blog.theme = theme blog.theme_modified = False blog.save() for n in export: with open(os.path.join(dir_name_final, n), "w", encoding='utf-8') as output_file: output_file.write(export[n]) save_tpl = 'listing/report' status = Status(type='success', close=False, message=''' Theme <b>{}</b> was successfully saved from blog <b>{}</b>. '''.format('', blog.for_display, ''), action='Return to theme list', url='{}/blog/{}/themes'.format(BASE_URL, blog.id)) else: save_tpl = 'edit/theme_save' status = None tags.status = status if reason is None else reason import datetime # TODO: eventually this will be migrated to the report function # but it's a little complex for that now due to the funtion logic return template( save_tpl, menu=generate_menu('blog_save_theme', blog), # search_context=(search_context['blog'], blog), theme_title=blog.theme.title + " (Revised {})".format(datetime.datetime.now()), theme_description=blog.theme.description, msg_float=False, **tags.__dict__)
def template_refresh(template_id): ''' UI for reloading a template from the original version stored in the template's theme (assuming such an original template exists) ''' user = auth.is_logged_in(request) tpl = Template.load(template_id) blog = Blog.load(tpl.blog) permission = auth.is_blog_designer(user, blog) from core.utils import Status import settings tags = template_tags(template_id=tpl.id, user=user) if request.forms.getunicode('confirm') == user.logout_nonce: import os, json template_path = (os.path.join(tpl.theme.path, tpl.template_ref)) with open(template_path, 'r') as f: tp_json = json.loads(f.read()) # TODO: We will eventually merge in all the other refresh functions # and convert this to a generic function called from # mgmt.theme_apply_to_blog as well with open(template_path[:-5] + '.tpl', 'r') as b: tpl.body = b.read() tpl.save(user) status = Status( type='success', close=False, message= 'Template <b>{}</b> was successfully refreshed from theme <b>{}</b>.' .format(tpl.for_display, tpl.theme.for_display), action='Return to template', url='{}/template/{}/edit'.format(settings.BASE_URL, tpl.id)) else: status = Status(type='warning', close=False, message=''' You are attempting to refresh template <b>{}</b> for blog <b>{}</b> from its underlying theme <b>{}</b>.</p> <p>This will <b>overwrite</b> the current version of the template and replace it with the original version from the theme. '''.format(tpl.for_display, blog.for_display, tpl.theme.for_display), no={ 'url': '{}/template/{}/edit'.format( settings.BASE_URL, tpl.id), 'label': 'No, I don\'t want to replace this template' }, yes={ 'id': 'delete', 'name': 'confirm', 'label': 'Yes, I want to replace this template', 'value': user.logout_nonce }) tags.status = status return report(tags, 'blog_delete_template', tpl)
def tag_delete(blog_id, tag_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) auth.check_tag_editing_lock(blog) try: tag = Tag.get(Tag.id == tag_id, Tag.blog == blog_id) except Tag.DoesNotExist: raise Tag.DoesNotExist("No such tag #{} in blog {}.".format( tag_id, blog.for_log)) from settings import BASE_URL tag_page_count = tag.pages.count() if request.forms.getunicode('confirm') == user.logout_nonce: from core.models import db if tag_page_count > 0: p_count = tag.pages.published.count() from core.cms import queue with db.atomic() as txn: queue.queue_page_actions(tag.pages.published) queue.queue_ssi_actions(blog) queue.queue_index_actions(blog, True) recommendation = ''' <p><b>{}</b> pages affected by this change have been pushed to the queue.</p> '''.format(p_count) else: recommendation = ''' <p>No pages were associated with this tag.</p> ''' with db.atomic() as txn: tag.delete_instance(recursive=True) status = Status(type='success', close=False, message=''' Tag <b>{}</b> was successfully deleted from blog <b>{}</b>.</p>{} '''.format(tag.for_log, blog.for_display, recommendation)) else: if tag_page_count > 0: recommendation = ''' <p><b>There are still <a target="_blank" href="{}/blog/{}/tag/{}/pages">{} pages</a> associated with this tag.</b></p> '''.format(BASE_URL, blog.id, tag.id, tag_page_count) tag_modified = tag_recently_modified(tag) if tag_modified: recommendation += "<p><b>" + tag_modified + "</b></p>" else: recommendation = '' status = Status(type='warning', close=False, message=''' You are about to delete tag <b>{}</b> in blog <b>{}</b>.</p>{} '''.format(tag.for_listing, blog.for_display, recommendation), url='{}/blog/{}/tag/{}/delete'.format( BASE_URL, blog.id, tag.id), yes={ 'id': 'delete', 'name': 'confirm', 'label': 'Yes, I want to delete this tag', 'value': user.logout_nonce }, no={ 'label': 'No, don\'t delete this tag', 'url': '{}/blog/{}/tag/{}'.format(BASE_URL, blog.id, tag.id) }) tags = template_tags(user=user) tags.status = status return report(tags, 'blog_delete_tag', tag)
def tag_edit(blog_id, tag_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_editor(user, blog) auth.check_tag_editing_lock(blog) try: tag = Tag.get(Tag.id == tag_id, Tag.blog == blog_id) except Tag.DoesNotExist: raise Tag.DoesNotExist("No such tag #{} in blog {}.".format( tag_id, blog.for_log)) tags = template_tags(user=user) from core.utils import html_escape if request.method == "POST": new_tag_name = request.forms.getunicode('tag_name') if new_tag_name != tag.tag: try: Tag.get(Tag.tag == new_tag_name) except Tag.DoesNotExist: tag_count = tag.pages.count() msg = "Tag changed from {} to <b>{}</b>. {} pages (and their archives) have been queued for republishing.".format( tag.for_log, html_escape(new_tag_name), tag_count) tag.tag = new_tag_name tag.save() if tag_count > 0: from core.cms import queue from core.models import db with db.atomic() as txn: queue.queue_page_actions(tag.pages.published) queue.queue_ssi_actions(blog) queue.queue_index_actions(blog, True) tags.status = Status(type='info', message=msg) else: msg = "Tag not renamed. A tag with the name '{}' already exists.".format( html_escape(new_tag_name)) tags.status = Status(type='danger', message=msg, no_sure=True) else: tag_modified = tag_recently_modified(tag) if tag_modified: tags.status = Status(type='danger', message=tag_modified, no_sure=True) tpl = template('edit/tag', menu=generate_menu('blog_edit_tag', tag), search_context=(search_contexts['sites'], None), tag=tag, **tags.__dict__) return tpl
def system_delete_theme(theme_id): user = auth.is_logged_in(request) permission = auth.is_sys_admin(user) # TODO: attach an installing user to the theme # allow that user to delete tags = template_tags(user=user) from core.models import Theme from settings import BASE_URL from core.utils import Status theme = Theme.load(theme_id) if request.forms.getunicode('confirm') == user.logout_nonce: from settings import THEME_FILE_PATH # , _sep import shutil, os shutil.rmtree(os.path.join(THEME_FILE_PATH, theme.json)) theme.delete_instance() status = Status(type='success', close=False, message=''' Theme <b>{}</b> was successfully deleted from the system.</p> '''.format(theme.for_log), action='Return to theme list', url='{}/system/themes'.format(BASE_URL)) else: m1 = '''You are about to remove theme <b>{}</b>. <b>THIS ACTION CANNOT BE UNDONE.</b></p> '''.format(theme.for_display) blogs_with_theme = Blog.select().where(Blog.theme == theme_id) if blogs_with_theme.count() > 0: used_in = [] for n in blogs_with_theme: used_in.append("<li>{}</li>".format(n.for_display)) m2 = '''<p>This theme is in use by the following blogs:<ul>{}</ul> Deleting this theme may <i>break these blogs entirely!</i></p> '''.format(''.join(used_in)) else: m2 = '' status = Status(type='warning', close=False, message=m1 + m2, url='{}/system/theme/{}/delete'.format( BASE_URL, theme.id), yes={ 'id': 'delete', 'name': 'confirm', 'label': 'Yes, I want to delete this theme', 'value': user.logout_nonce }, no={ 'label': 'No, don\'t delete this theme', 'url': '{}/system/themes'.format(BASE_URL) }) tags.status = status return report(tags, 'system_delete_theme', theme)
def page_delete(page_id, confirm): ''' Deletes a selected page -- no confirmation yet Returns user to list of pages in blog with a notice about the deleted file ''' user = auth.is_logged_in(request) page = Page.load(page_id) permission = auth.is_page_editor(user, page) blog = page.blog from core.utils import Status tags = template_tags(page=page, user=user) from core.models import page_status if page.status != page_status.unpublished: message = 'Page <b>{}</b> is not set to unpublished and cannot be deleted. Unpublish this page before deleting it.'.format( page.for_display) url = '{}/blog/{}'.format(BASE_URL, blog.id) action = 'Return to the page listing' tags.status = Status(type='danger', no_sure=True, message=message, action=action, url=url, close=False) else: if request.forms.getunicode('confirm') == user.logout_nonce: p = page.for_log from core.cms.cms import delete_page delete_page(page) message = 'Page {} successfully deleted'.format(p) url = '{}/blog/{}'.format(BASE_URL, blog.id) action = 'Return to the page listing' tags.status = Status(type='success', message=message, action=action, url=url, close=False) logger.info("Page {} deleted by user {}.".format(p, user.for_log)) else: message = ( 'You are about to delete page <b>{}</b> from blog <b>{}</b>.'. format(page.for_display, blog.for_display)) yes = { 'label': 'Yes, delete this page', 'id': 'delete', 'name': 'confirm', 'value': user.logout_nonce } no = { 'label': 'No, return to blog page listing', 'url': '{}/blog/{}'.format(BASE_URL, blog.id) } tags.status = Status(message=message, type='warning', close=False, yes=yes, no=no) return report(tags, 'blog_delete_page', page)
def save_page(page, user, blog=None): ''' Saves edits to a page in the CMS. Note that this function does _not_ perform permission checking. In other words, it doesn't verify if the user described in the `user` parameter does in fact have permissions to edit the page in question. :param page: Page object whose data is to be saved. If this is None, then it is assumed that we are creating a new page. :param user: The user object associated with the save action for this page. If this is a newly-created page, the page's user will be set to this. :param blog: The blog object under which the page will be created, if this is a newly-created page. ''' getunicode = request.forms.getunicode # invalidate_cache() save_action = int(request.forms.get('save')) original_page_status = page_status.unpublished new_basename = getunicode('basename') if page is None: # CREATE NEW PAGE ENTRY page = Page() page.user = user.id page.blog = blog.id page.basename = create_basename(getunicode('page_title'), page.blog) original_page_basename = page.basename time_now = datetime.datetime.utcnow() page.publication_date = time_now page.created_date = time_now else: # UPDATE EXISTING ENTRY # Queue neighbor actions for page BEFORE modification if page.status == page_status.published: if not (save_action & save_action_list.UNPUBLISH_PAGE): queue_page_actions((page.next_page, page.previous_page), no_neighbors=True, no_archive=True) queue_page_archive_actions(page) original_page_status = page.status original_page_basename = page.basename page.modified_date = datetime.datetime.utcnow() change_basename = False if new_basename is not None: if new_basename == "": change_basename = True new_basename = create_basename(getunicode('page_title'), page.blog) if new_basename != original_page_basename: change_basename = True new_publication_date = datetime.datetime.strptime( request.forms.get('publication_date'), DATE_FORMAT) if change_basename: page.basename = create_basename(new_basename, page.blog) page.publication_date = page._date_to_utc( page.blog.timezone, new_publication_date).replace(tzinfo=None) page.title = getunicode('page_title') page.text = getunicode('page_text') page.status = page_status.modes[int( request.forms.get('publication_status'))] page.tag_text = getunicode('page_tag_text') page.excerpt = getunicode('page_excerpt') change_note = getunicode('change_note') msg = [] # UNPUBLISH if ((save_action & save_action_list.UNPUBLISH_PAGE and page.status == page_status.published) or # unpublished a published page (original_page_status == page_status.published and page.status == page_status.unpublished ) # set a published page to draft ): unpublish_page(page) msg.append("Page <b>{}</b> unpublished successfully.") # SET UNPUBLISHED TO PUBLISHED elif original_page_status == page_status.unpublished and ( save_action & save_action_list.UPDATE_LIVE_PAGE): page.status = page_status.published msg.append("Set to publish.") # SAVE DRAFT if (save_action & save_action_list.SAVE_TO_DRAFT): try: save_result = page.save(user, False, False, change_note) except PageNotChanged: save_result = (None, None) msg.append("Page <b>{}</b> saved successfully.") # Assign categories for page categories = [] for n in request.forms.allitems(): if n[0][:8] == 'cat-sel-': try: category_id = int(n[0][8:]) except ValueError: category_id = None else: categories.append(category_id) if not categories: categories.append(blog.default_category.id) msg.append(" Default category auto-assigned for page.") page_categories = [] primary = None for n in page.categories: if n.category.id not in categories: delete_category = PageCategory.delete().where( PageCategory.id == n.id) delete_category.execute() else: page_categories.append(n.category.id) if n.primary is True: primary = n for n in categories: if n not in page_categories: new_page_category = PageCategory.create( page=page, category=Category.load(n, blog_id=page.blog.id), primary=False) if primary is None: n = page.categories[0] n.primary = True n.save() delete_page_fileinfo(page) build_archives_fileinfos((page, )) build_pages_fileinfos((page, )) # UPDATE TAGS if getunicode('tag_text') is not None: import json tag_text = json.loads(getunicode('tag_text')) add_tags_to_page(tag_text, page) delete_orphaned_tags(page.blog) # QUEUE CHANGES FOR PUBLICATION (if any) if ((save_action & save_action_list.UPDATE_LIVE_PAGE) and (page.status == page_status.published)): queue_ssi_actions(page.blog) queue_page_actions((page, )) queue_index_actions(page.blog) msg.append(" Live page updated.") # DETECT ANY PAGE CHANGES if ((save_action & (save_action_list.SAVE_TO_DRAFT + save_action_list.UPDATE_LIVE_PAGE)) and (save_result[1]) is None): msg.append(" (Page unchanged.)") # RETURN REPORT tags = template_tags(page=page, user=user) status = Status(type='success', message=' / '.join(msg), vals=(page.for_log, )) tags.status = status tags._save_action = save_action tags._save_action_list = save_action_list return tags
def save_page(page, user, blog=None): ''' Saves edits to a page in the CMS. Note that this function does _not_ perform permission checking. In other words, it doesn't verify if the user described in the `user` parameter does in fact have permissions to edit the page in question. ''' save_action = int(request.forms.get('save')) blog_new_page = False original_page_status = page_status.unpublished if page is None: blog_new_page = True page = Page() page.user = user.id page.blog = blog.id page.basename = create_basename(request.forms.getunicode('page_title'), page.blog) original_page_basename = page.basename page.publication_date = datetime.datetime.now() page.created_date = datetime.datetime.now() else: original_page_status = page.status original_page_basename = page.basename page.modified_date = datetime.datetime.now() if request.forms.getunicode('basename') is not None: if request.forms.getunicode('basename') != "": if original_page_basename != request.forms.getunicode( 'basename'): page.basename = create_basename( request.forms.getunicode('basename'), page.blog) else: page.basename = create_basename( request.forms.getunicode('page_title'), page.blog) if original_page_basename != page.basename: delete_page_fileinfo(page) if page.basename == "": page.basename = create_basename(request.forms.getunicode('page_title'), page.blog) original_page_basename = page.basename page.title = request.forms.getunicode('page_title') page.text = request.forms.getunicode('page_text') page.status = page_status.modes[int( request.forms.get('publication_status'))] page.publication_date = datetime.datetime.strptime( request.forms.get('publication_date'), '%Y-%m-%d %H:%M:%S') page.tag_text = request.forms.getunicode('page_tag_text') page.excerpt = request.forms.getunicode('page_excerpt') change_note = request.forms.getunicode('change_note') # Save to draft only # Save and publish # Save and exit # Republish and exit # Unpublish (and exit) # Delete (and unpublish) (and exit) msg = "" # UNPUBLISH if ((save_action & save_action_list.UNPUBLISH_PAGE and page.status == page_status.published) or # unpublished a published page (original_page_status == page_status.published and page.status == page_status.unpublished) or # set a published page to draft (save_action & save_action_list.DELETE_PAGE ) # delete a page, regardless of status ): pass # DELETE; IMPLIES UNPUBLISH if (save_action & save_action_list.DELETE_PAGE): pass # UNPUBLISHED TO PUBLISHED if original_page_status == page_status.unpublished and ( save_action & save_action_list.UPDATE_LIVE_PAGE): page.status = page_status.published # SAVE DRAFT if (save_action & save_action_list.SAVE_TO_DRAFT): backup_only = True if request.forms.getunicode( 'draft') == "Y" else False try: save_result = page.save(user, False, backup_only, change_note) except PageNotChanged: save_result = (None, None) if blog_new_page: default_blog_category = Category.get(Category.blog == blog.id, Category.default == True) saved_page_category = PageCategory.create( page=page, category=default_blog_category, primary=True) msg += ("Page <b>{}</b> saved.") # SET TAGS # when to do this? # what happens when we delete a page? # all tags for a page have to be deassigned. if request.forms.getunicode('tag_text') is not None: tag_text = json.loads(request.forms.getunicode('tag_text')) add_tags_to_page(tag_text, page) delete_orphaned_tags() # BUILD FILEINFO IF NO DELETE ACTION if not (save_action & save_action_list.DELETE_PAGE): build_pages_fileinfos((page, )) build_archives_fileinfos((page, )) # PUBLISH CHANGES if (save_action & save_action_list.UPDATE_LIVE_PAGE) and ( page.status == page_status.published): queue_page_actions(page) queue_index_actions(page.blog) msg += (" Live page updated.") if (save_action & (save_action_list.SAVE_TO_DRAFT + save_action_list.UPDATE_LIVE_PAGE)) and (save_result[1]) is None: msg += (" (Page unchanged.)") tags = template_tags(page_id=page.id, user=user) status = Status(type='success', message=msg, vals=(page.title, )) tags.status = status return tags
def edit_category(blog_id, category_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) category = Category.load(category_id, blog_id=blog.id) auth.check_category_editing_lock(blog) category_list = [n for n in blog.categories] top_level_category = Category(id=None, title='[Top-level category]', parent=None) category_list.insert(0, top_level_category) tags = template_tags(blog=blog, user=user) from core.utils import Status status = [] if request.method == "POST": new_category_title = request.forms.getunicode('category_title') old_category_title = category.title if new_category_title != old_category_title: category.title = new_category_title category.save() status.append([ 'Category <b>{}</b> was renamed to <b>{}</b>.', [old_category_title, new_category_title] ]) old_parent_category = category.parent_category try: new_parent_category = int( request.forms.getunicode('category_parent')) except ValueError: new_parent_category = None new_basename = request.forms.getunicode('category_basename') if category.basename != new_basename: category.basename = new_basename category.save() status.append(['Category basename was changed.', []]) if old_parent_category != new_parent_category: category.parent_category = new_parent_category category.save() if new_parent_category is not None: new_category = Category.load(category_id=new_parent_category, blog=blog) else: new_category = top_level_category status.append([ 'Category <b>{}</b> was reparented to <b>{}</b>.', [category.title, new_category.for_log] ]) if request.forms.getunicode('default') == "Y": clear_default_categories = Category.update(default=False).where( Category.blog == blog, Category.default == True) clear_default_categories.execute() category.default = True category.save() status.append([ 'Category <b>{}</b> was set to default for blog <b>{}</b>.', [category.title, blog.for_log] ]) if len(status) > 0: message = '' vals = [] for n in status: message += n[0] for m in n[1]: vals.append(m) vals.append('{}/blog/{}/purge'.format(BASE_URL, blog.id)) tags.status = Status( type='success', message=message + '<br/><a href="{}">Purge and republish this blog</a> to make these changes take effect.', vals=vals) # from core.ui_kv import kv_ui from core.ui import kv kv_ui_data = kv.ui(category.kv_list()) from core.ui import sidebar tags.sidebar = sidebar.render_sidebar( panel_set='edit_category', # status_badge=status_badge, kv_object='Category', kv_objectid=category.id, kv_ui=kv_ui_data) tpl = template('edit/category', category=category, category_list=category_list, menu=generate_menu('blog_edit_category', category), search_context=(search_contexts['sites'], None), **tags.__dict__) return tpl