Exemple #1
0
def create(request):
    """
    Create a new wiki page, which is a document and a revision.
    """
    initial_slug = request.GET.get('slug', '')

    # TODO: Integrate this into a new exception-handling middleware
    if not request.user.has_perm('wiki.add_document'):
        context = {
            'reason': 'create-page',
            'request_page_url': DEV_DOC_REQUEST_FORM,
            'email_address': config.EMAIL_LIST_MDN_ADMINS
        }
        return render(request,
                      '403-create-page.html',
                      context=context,
                      status=403)

    # a fake title based on the initial slug passed via a query parameter
    initial_title = initial_slug.replace('_', ' ')

    # in case we want to create a sub page under a different document
    try:
        # If a parent ID is provided via GET, confirm it exists
        initial_parent_id = int(request.GET.get('parent', ''))
        parent_doc = Document.objects.get(pk=initial_parent_id)
        parent_slug = parent_doc.slug
        parent_path = parent_doc.get_absolute_url()
    except (ValueError, Document.DoesNotExist):
        initial_parent_id = parent_slug = parent_path = ''

    # in case we want to create a new page by cloning an existing document
    try:
        clone_id = int(request.GET.get('clone', ''))
    except ValueError:
        clone_id = None

    context = {
        'attachment_form': AttachmentRevisionForm(),
        'parent_path': parent_path,
        'parent_slug': parent_slug,
    }

    if request.method == 'GET':

        initial_data = {}
        initial_html = ''
        initial_tags = ''
        initial_toc = Revision.TOC_DEPTH_H4

        if clone_id:
            try:
                clone_doc = Document.objects.get(pk=clone_id)
                initial_title = clone_doc.title
                initial_html = clone_doc.html
                initial_tags = clone_doc.tags.all()
                if clone_doc.current_revision:
                    initial_toc = clone_doc.current_revision.toc_depth
                else:
                    initial_toc = 1

            except Document.DoesNotExist:
                pass

        if parent_slug:
            initial_data['parent_topic'] = initial_parent_id

        if initial_slug:
            initial_data['title'] = initial_title
            initial_data['slug'] = initial_slug

        review_tags = REVIEW_FLAG_TAGS_DEFAULT

        doc_form = DocumentForm(initial=initial_data, parent_slug=parent_slug)

        initial = {
            'slug': initial_slug,
            'title': initial_title,
            'content': initial_html,
            'review_tags': review_tags,
            'tags': initial_tags,
            'toc_depth': initial_toc
        }
        rev_form = RevisionForm(request=request, initial=initial)

        context.update({
            'parent_id': initial_parent_id,
            'document_form': doc_form,
            'revision_form': rev_form,
            'initial_tags': initial_tags,
        })

    else:

        submitted_data = request.POST.copy()
        posted_slug = submitted_data['slug']
        submitted_data['locale'] = request.LANGUAGE_CODE
        if parent_slug:
            submitted_data['parent_topic'] = initial_parent_id

        doc_form = DocumentForm(data=submitted_data, parent_slug=parent_slug)
        rev_form = RevisionForm(request=request,
                                data=submitted_data,
                                parent_slug=parent_slug)

        if doc_form.is_valid() and rev_form.is_valid():
            doc = doc_form.save(parent=None)
            rev_form.save(doc)
            if doc.current_revision.is_approved:
                view = 'wiki.document'
            else:
                view = 'wiki.document_revisions'
            return redirect(reverse(view, args=[doc.slug]))
        else:
            doc_form.data['slug'] = posted_slug

        context.update({
            'document_form': doc_form,
            'revision_form': rev_form,
        })

    return render(request, 'wiki/create.html', context)
Exemple #2
0
def translate(request, document_slug, document_locale):
    """
    Create a new translation of a wiki document.

    * document_slug is for the default locale
    * translation is to the request locale
    """
    # TODO: Refactor this view into two views? (new, edit)
    # That might help reduce the headache-inducing branchiness.

    # The parent document to translate from
    parent_doc = get_object_or_404(Document,
                                   locale=settings.WIKI_DEFAULT_LANGUAGE,
                                   slug=document_slug)

    # HACK: Seems weird, but sticking the translate-to locale in a query
    # param is the best way to avoid the MindTouch-legacy locale
    # redirection logic.
    document_locale = request.GET.get('tolocale', document_locale)

    # Set a "Discard Changes" page
    discard_href = ''

    if settings.WIKI_DEFAULT_LANGUAGE == document_locale:
        # Don't translate to the default language.
        return redirect(
            reverse('wiki.edit',
                    locale=settings.WIKI_DEFAULT_LANGUAGE,
                    args=[parent_doc.slug]))

    if not parent_doc.is_localizable:
        message = _(u'You cannot translate this document.')
        context = {'message': message}
        return render(request, 'handlers/400.html', context, status=400)

    based_on_rev = parent_doc.current_or_latest_revision()

    disclose_description = bool(request.GET.get('opendescription'))

    try:
        doc = parent_doc.translations.get(locale=document_locale)
        slug_dict = split_slug(doc.slug)
    except Document.DoesNotExist:
        doc = None
        disclose_description = True
        slug_dict = split_slug(document_slug)

        # Find the "real" parent topic, which is its translation
        if parent_doc.parent_topic:
            try:
                parent_topic_translated_doc = (
                    parent_doc.parent_topic.translations.get(
                        locale=document_locale))
                slug_dict = split_slug(parent_topic_translated_doc.slug + '/' +
                                       slug_dict['specific'])
            except ObjectDoesNotExist:
                pass

    user_has_doc_perm = (not doc) or (doc
                                      and doc.allows_editing_by(request.user))

    doc_form = None
    if user_has_doc_perm:
        if doc:
            # If there's an existing doc, populate form from it.
            discard_href = doc.get_absolute_url()
            doc.slug = slug_dict['specific']
            doc_initial = document_form_initial(doc)
        else:
            # If no existing doc, bring over the original title and slug.
            discard_href = parent_doc.get_absolute_url()
            doc_initial = {
                'title': based_on_rev.title,
                'slug': slug_dict['specific']
            }
        doc_form = DocumentForm(initial=doc_initial,
                                parent_slug=slug_dict['parent'])

    initial = {
        'based_on': based_on_rev.id,
        'current_rev': doc.current_or_latest_revision().id if doc else None,
        'comment': '',
        'toc_depth': based_on_rev.toc_depth,
        'localization_tags': ['inprogress'],
    }
    content = None
    if not doc:
        content = based_on_rev.content
    if content:
        # TODO: There will be no need to "filterEditorSafety" when the code
        #       that calls "clean_content" on Revision.save is deployed to
        #       production, AND the current revisions of all docs have had
        #       their content cleaned with "clean_content".
        initial.update(content=kuma.wiki.content.parse(
            content).filterEditorSafety().serialize())
    instance = doc and doc.current_or_latest_revision()
    rev_form = RevisionForm(request=request,
                            instance=instance,
                            initial=initial,
                            parent_slug=slug_dict['parent'])

    if request.method == 'POST':
        which_form = request.POST.get('form-type', 'both')
        doc_form_invalid = False

        # Grab the posted slug value in case it's invalid
        posted_slug = request.POST.get('slug', slug_dict['specific'])

        if user_has_doc_perm and which_form in ['doc', 'both']:
            disclose_description = True
            post_data = request.POST.copy()

            post_data.update({'locale': document_locale})

            doc_form = DocumentForm(post_data,
                                    instance=doc,
                                    parent_slug=slug_dict['parent'])
            doc_form.instance.locale = document_locale
            doc_form.instance.parent = parent_doc

            if which_form == 'both':
                # Sending a new copy of post so the slug change above
                # doesn't cause problems during validation
                rev_form = RevisionForm(request=request,
                                        data=post_data,
                                        parent_slug=slug_dict['parent'])

            # If we are submitting the whole form, we need to check that
            # the Revision is valid before saving the Document.
            if doc_form.is_valid() and (which_form == 'doc'
                                        or rev_form.is_valid()):
                doc = doc_form.save(parent=parent_doc)

                if which_form == 'doc':
                    url = urlparams(doc.get_edit_url(), opendescription=1)
                    return redirect(url)
            else:
                doc_form.data['slug'] = posted_slug
                doc_form_invalid = True

        if doc and which_form in ['rev', 'both']:
            post_data = request.POST.copy()
            if 'slug' not in post_data:
                post_data['slug'] = posted_slug

            # update the post data with the toc_depth of original
            post_data['toc_depth'] = based_on_rev.toc_depth

            # Pass in the locale for the akistmet "blog_lang".
            post_data['locale'] = document_locale

            rev_form = RevisionForm(request=request,
                                    data=post_data,
                                    parent_slug=slug_dict['parent'])
            rev_form.instance.document = doc  # for rev_form.clean()

            if rev_form.is_valid() and not doc_form_invalid:
                parent_id = request.POST.get('parent_id', '')

                # Attempt to set a parent
                if parent_id:
                    try:
                        parent_doc = get_object_or_404(Document, id=parent_id)
                        rev_form.instance.document.parent = parent_doc
                        doc.parent = parent_doc
                        rev_form.instance.based_on.document = doc.original
                    except Document.DoesNotExist:
                        pass

                rev_form.save(doc)
                # If this is an Ajax POST, then return a JsonResponse
                if request.is_ajax():
                    data = {
                        'error': False,
                        'new_revision_id': rev_form.instance.id,
                    }

                    return JsonResponse(data)

                # Construct the redirect URL, adding any needed parameters
                url = doc.get_absolute_url()
                params = {}
                # Parameter for the document saved, so that we can delete the cached draft on load
                params['rev_saved'] = request.POST.get('current_rev', '')
                url = '%s?%s' % (url, urlencode(params))
                return redirect(url)
            else:
                # If this is an Ajax POST, then return a JsonResponse with error
                if request.is_ajax():
                    if 'current_rev' in rev_form._errors:
                        # Make the error message safe so the '<' and '>' don't
                        # get turned into '&lt;' and '&gt;', respectively
                        rev_form.errors['current_rev'][0] = mark_safe(
                            rev_form.errors['current_rev'][0])
                    errors = [
                        rev_form.errors[key][0]
                        for key in rev_form.errors.keys()
                    ]
                    data = {
                        "error": True,
                        "error_message": errors,
                        "new_revision_id": rev_form.instance.id,
                    }
                    return JsonResponse(data=data)

    if doc:
        from_id = smart_int(request.GET.get('from'), None)
        to_id = smart_int(request.GET.get('to'), None)

        revision_from = get_object_or_none(Revision,
                                           pk=from_id,
                                           document=doc.parent)
        revision_to = get_object_or_none(Revision,
                                         pk=to_id,
                                         document=doc.parent)
    else:
        revision_from = revision_to = None

    parent_split = split_slug(parent_doc.slug)

    language_mapping = get_language_mapping()
    language = language_mapping[document_locale.lower()]
    default_locale = language_mapping[settings.WIKI_DEFAULT_LANGUAGE.lower()]

    context = {
        'parent': parent_doc,
        'document': doc,
        'document_form': doc_form,
        'revision_form': rev_form,
        'locale': document_locale,
        'default_locale': default_locale,
        'language': language,
        'based_on': based_on_rev,
        'disclose_description': disclose_description,
        'discard_href': discard_href,
        'attachment_form': AttachmentRevisionForm(),
        'specific_slug': parent_split['specific'],
        'parent_slug': parent_split['parent'],
        'revision_from': revision_from,
        'revision_to': revision_to,
    }
    return render(request, 'wiki/translate.html', context)
Exemple #3
0
def edit(request, document_slug, document_locale):
    """
    Create a new revision of a wiki document, or edit document metadata.
    """
    doc = get_object_or_404(Document,
                            locale=document_locale,
                            slug=document_slug)

    # If this document has a parent, then the edit is handled by the
    # translate view. Pass it on.
    if doc.parent and doc.parent.id != doc.id:
        return translate(request, doc.parent.slug, doc.locale,
                         bypass_process_document_path=True)

    rev = doc.current_revision or doc.revisions.order_by('-created', '-id')[0]

    # Keep hold of the full post slug
    slug_dict = split_slug(document_slug)
    # Update the slug, removing the parent path, and
    # *only* using the last piece.
    # This is only for the edit form.
    rev.slug = slug_dict['specific']

    section_id = request.GET.get('section', None)
    if section_id and not request.is_ajax():
        return HttpResponse(ugettext("Sections may only be edited inline."))
    disclose_description = bool(request.GET.get('opendescription'))

    doc_form = rev_form = None
    rev_form = RevisionForm(request=request,
                            instance=rev,
                            initial={'based_on': rev.id,
                                     'current_rev': rev.id,
                                     'comment': ''},
                            section_id=section_id)
    if doc.allows_editing_by(request.user):
        doc_form = DocumentForm(initial=document_form_initial(doc))

    # Need to make check *here* to see if this could have a translation parent
    show_translation_parent_block = (
        (document_locale != settings.WIKI_DEFAULT_LANGUAGE) and
        (not doc.parent_id))

    if request.method == 'GET':
        if not (rev_form or doc_form):
            # You can't do anything on this page, so get lost.
            raise PermissionDenied

    else:  # POST
        is_async_submit = request.is_ajax()
        is_raw = request.GET.get('raw', False)
        need_edit_links = request.GET.get('edit_links', False)
        parent_id = request.POST.get('parent_id', '')

        # Attempt to set a parent
        if show_translation_parent_block and parent_id:
            try:
                parent_doc = get_object_or_404(Document, id=parent_id)
                doc.parent = parent_doc
            except Document.DoesNotExist:
                pass

        # Comparing against localized names for the Save button bothers me, so
        # I embedded a hidden input:
        which_form = request.POST.get('form-type')

        if which_form == 'doc':
            if doc.allows_editing_by(request.user):
                post_data = request.POST.copy()

                post_data.update({'locale': document_locale})
                doc_form = DocumentForm(post_data, instance=doc)
                if doc_form.is_valid():
                    # if must be here for section edits
                    if 'slug' in post_data:
                        post_data['slug'] = u'/'.join([slug_dict['parent'],
                                                       post_data['slug']])

                    # Get the possibly new slug for the imminent redirection:
                    doc = doc_form.save(parent=None)

                    return redirect(urlparams(doc.get_edit_url(),
                                              opendescription=1))
                disclose_description = True
            else:
                raise PermissionDenied

        elif which_form == 'rev':
            post_data = request.POST.copy()

            rev_form = RevisionForm(request=request,
                                    data=post_data,
                                    is_async_submit=is_async_submit,
                                    section_id=section_id)
            rev_form.instance.document = doc  # for rev_form.clean()

            # Come up with the original revision to which these changes
            # would be applied.
            orig_rev_id = request.POST.get('current_rev', False)
            if orig_rev_id is False:
                orig_rev = None
            else:
                orig_rev = Revision.objects.get(pk=orig_rev_id)
            # Get the document's actual current revision.
            curr_rev = doc.current_revision

            if not rev_form.is_valid():
                # If this was an Ajax POST, then return a JsonResponse
                if is_async_submit:
                    # Was there a mid-air collision?
                    if 'current_rev' in rev_form._errors:
                        # Make the error message safe so the '<' and '>' don't
                        # get turned into '&lt;' and '&gt;', respectively
                        rev_form.errors['current_rev'][0] = mark_safe(
                            rev_form.errors['current_rev'][0])
                    errors = [rev_form.errors[key][0] for key in rev_form.errors.keys()]

                    data = {
                        "error": True,
                        "error_message": errors,
                        "new_revision_id": curr_rev.id,
                    }
                    return JsonResponse(data=data)
                    # Jump out to a function to escape indentation hell
                    return _edit_document_collision(
                        request, orig_rev, curr_rev, is_async_submit,
                        is_raw, rev_form, doc_form, section_id,
                        rev, doc)
                # Was this an Ajax submission that was marked as spam?
                if is_async_submit and '__all__' in rev_form._errors:
                    # Return a JsonResponse
                    data = {
                        "error": True,
                        "error_message": mark_safe(rev_form.errors['__all__'][0]),
                        "new_revision_id": curr_rev.id,
                    }
                    return JsonResponse(data=data)
            if rev_form.is_valid():
                rev_form.save(doc)
                if (is_raw and orig_rev is not None and
                        curr_rev.id != orig_rev.id):
                    # If this is the raw view, and there was an original
                    # revision, but the original revision differed from the
                    # current revision at start of editing, we should tell
                    # the client to refresh the page.
                    response = HttpResponse('RESET')
                    response['X-Frame-Options'] = 'SAMEORIGIN'
                    response.status_code = 205
                    return response
                # Is this an Ajax POST?
                if is_async_submit:
                    # This is the most recent revision id
                    new_rev_id = rev.document.revisions.order_by('-id').first().id
                    data = {
                        "error": False,
                        "new_revision_id": new_rev_id
                    }
                    return JsonResponse(data)

                if rev_form.instance.is_approved:
                    view = 'wiki.document'
                else:
                    view = 'wiki.document_revisions'

                # Construct the redirect URL, adding any needed parameters
                url = reverse(view, args=[doc.slug], locale=doc.locale)
                params = {}
                if is_raw:
                    params['raw'] = 'true'
                    if need_edit_links:
                        # Only need to carry over ?edit_links with ?raw,
                        # because they're on by default in the normal UI
                        params['edit_links'] = 'true'
                    if section_id:
                        # If a section was edited, and we're using the raw
                        # content API, constrain to that section.
                        params['section'] = section_id
                # Parameter for the document saved, so that we can delete the cached draft on load
                params['rev_saved'] = curr_rev.id if curr_rev else ''
                url = '%s?%s' % (url, urlencode(params))
                if not is_raw and section_id:
                    # If a section was edited, jump to the section anchor
                    # if we're not getting raw content.
                    url = '%s#%s' % (url, section_id)
                return redirect(url)

    parent_path = parent_slug = ''
    if slug_dict['parent']:
        parent_slug = slug_dict['parent']

    if doc.parent_topic_id:
        parent_doc = Document.objects.get(pk=doc.parent_topic_id)
        parent_path = parent_doc.get_absolute_url()
        parent_slug = parent_doc.slug

    context = {
        'revision_form': rev_form,
        'document_form': doc_form,
        'section_id': section_id,
        'disclose_description': disclose_description,
        'parent_slug': parent_slug,
        'parent_path': parent_path,
        'revision': rev,
        'document': doc,
        'attachment_form': AttachmentRevisionForm(),
    }
    return render(request, 'wiki/edit.html', context)
Exemple #4
0
def create(request):
    """
    Create a new wiki page, which is a document and a revision.
    """
    initial_slug = request.GET.get("slug", "")

    # TODO: Integrate this into a new exception-handling middleware
    if not request.user.has_perm("wiki.add_document"):
        context = {
            "reason": "create-page",
            "request_page_url": DEV_DOC_REQUEST_FORM,
            "email_address": settings.EMAIL_LIST_MDN_ADMINS,
        }
        return render(request,
                      "403-create-page.html",
                      context=context,
                      status=403)

    # a fake title based on the initial slug passed via a query parameter
    initial_title = initial_slug.replace("_", " ")

    # in case we want to create a sub page under a different document
    try:
        # If a parent ID is provided via GET, confirm it exists
        initial_parent_id = int(request.GET.get("parent", ""))
        parent_doc = Document.objects.get(pk=initial_parent_id)
        parent_slug = parent_doc.slug
        parent_path = parent_doc.get_absolute_url()
    except (ValueError, Document.DoesNotExist):
        initial_parent_id = parent_slug = parent_path = ""

    # in case we want to create a new page by cloning an existing document
    try:
        clone_id = int(request.GET.get("clone", ""))
    except ValueError:
        clone_id = None

    context = {
        "attachment_form": AttachmentRevisionForm(),
        "parent_path": parent_path,
        "parent_slug": parent_slug,
    }

    if request.method == "GET":

        initial_data = {}
        initial_html = ""
        initial_tags = ""
        initial_toc = Revision.TOC_DEPTH_H4

        if clone_id:
            try:
                clone_doc = Document.objects.get(pk=clone_id)
                initial_title = clone_doc.title
                initial_html = clone_doc.html
                initial_tags = clone_doc.tags.all()
                if clone_doc.current_revision:
                    initial_toc = clone_doc.current_revision.toc_depth
                else:
                    initial_toc = 1

            except Document.DoesNotExist:
                pass

        if parent_slug:
            initial_data["parent_topic"] = initial_parent_id

        if initial_slug:
            initial_data["title"] = initial_title
            initial_data["slug"] = initial_slug

        review_tags = REVIEW_FLAG_TAGS_DEFAULT

        doc_form = DocumentForm(initial=initial_data, parent_slug=parent_slug)

        initial = {
            "slug": initial_slug,
            "title": initial_title,
            "content": initial_html,
            "review_tags": review_tags,
            "tags": initial_tags,
            "toc_depth": initial_toc,
        }
        rev_form = RevisionForm(request=request, initial=initial)

        context.update({
            "parent_id": initial_parent_id,
            "document_form": doc_form,
            "revision_form": rev_form,
            "initial_tags": initial_tags,
        })

    else:

        submitted_data = request.POST.copy()
        posted_slug = submitted_data["slug"]
        submitted_data["locale"] = request.LANGUAGE_CODE
        if parent_slug:
            submitted_data["parent_topic"] = initial_parent_id

        doc_form = DocumentForm(data=submitted_data, parent_slug=parent_slug)
        rev_form = RevisionForm(request=request,
                                data=submitted_data,
                                parent_slug=parent_slug)

        if doc_form.is_valid() and rev_form.is_valid():
            doc = doc_form.save(parent=None)
            rev_form.save(doc)
            if doc.current_revision.is_approved:
                view = "wiki.document"
            else:
                view = "wiki.document_revisions"
            return redirect(reverse(view, args=[doc.slug]))
        else:
            doc_form.data["slug"] = posted_slug

        context.update({"document_form": doc_form, "revision_form": rev_form})

    return render(request, "wiki/create.html", context)
Exemple #5
0
def create(request):
    """
    Create a new wiki page, which is a document and a revision.
    """
    initial_slug = request.GET.get('slug', '')

    # Try to head off disallowed Template:* creation, right off the bat
    if not Document.objects.allows_add_by(request.user, initial_slug):
        raise PermissionDenied

    # if the initial slug indicates the creation of a new template
    is_template = initial_slug.startswith(TEMPLATE_TITLE_PREFIX)

    # a fake title based on the initial slug passed via a query parameter
    initial_title = initial_slug.replace('_', ' ')

    # in case we want to create a sub page under a different document
    try:
        # If a parent ID is provided via GET, confirm it exists
        initial_parent_id = int(request.GET.get('parent', ''))
        parent_doc = Document.objects.get(pk=initial_parent_id)
        parent_slug = parent_doc.slug
        parent_path = parent_doc.get_absolute_url()
    except (ValueError, Document.DoesNotExist):
        initial_parent_id = parent_slug = parent_path = ''

    # in case we want to create a new page by cloning an existing document
    try:
        clone_id = int(request.GET.get('clone', ''))
    except ValueError:
        clone_id = None

    context = {
        'is_template': is_template,
        'attachment_form': AttachmentRevisionForm(),
        'parent_path': parent_path,
        'parent_slug': parent_slug,
    }

    if request.method == 'GET':

        initial_data = {}
        initial_html = ''
        initial_tags = ''
        initial_toc = Revision.TOC_DEPTH_H4

        if clone_id:
            try:
                clone_doc = Document.objects.get(pk=clone_id)
                initial_title = clone_doc.title
                initial_html = clone_doc.html
                initial_tags = clone_doc.tags.all()
                if clone_doc.current_revision:
                    initial_toc = clone_doc.current_revision.toc_depth
                else:
                    initial_toc = 1

            except Document.DoesNotExist:
                pass

        if parent_slug:
            initial_data['parent_topic'] = initial_parent_id

        if initial_slug:
            initial_data['title'] = initial_title
            initial_data['slug'] = initial_slug

        if is_template:
            review_tags = ('template',)
        else:
            review_tags = REVIEW_FLAG_TAGS_DEFAULT

        doc_form = DocumentForm(initial=initial_data, parent_slug=parent_slug)

        rev_form = RevisionForm(initial={
            'slug': initial_slug,
            'title': initial_title,
            'content': initial_html,
            'review_tags': review_tags,
            'tags': initial_tags,
            'toc_depth': initial_toc
        })

        context.update({
            'parent_id': initial_parent_id,
            'document_form': doc_form,
            'revision_form': rev_form,
            'initial_tags': initial_tags,
        })

    else:

        submitted_data = request.POST.copy()
        posted_slug = submitted_data['slug']
        submitted_data['locale'] = request.locale
        if parent_slug:
            submitted_data['parent_topic'] = initial_parent_id

        doc_form = DocumentForm(submitted_data, parent_slug=parent_slug)
        rev_form = RevisionForm(data=submitted_data, parent_slug=parent_slug)

        if doc_form.is_valid() and rev_form.is_valid():
            slug = doc_form.cleaned_data['slug']
            if not Document.objects.allows_add_by(request.user, slug):
                raise PermissionDenied

            doc = doc_form.save(parent=None)
            rev_form.save(request, doc)
            if doc.current_revision.is_approved:
                view = 'wiki.document'
            else:
                view = 'wiki.document_revisions'
            return redirect(reverse(view, args=[doc.slug]))
        else:
            doc_form.data['slug'] = posted_slug

        context.update({
            'document_form': doc_form,
            'revision_form': rev_form,
        })

    return render(request, 'wiki/create.html', context)
Exemple #6
0
def translate(request, document_slug, document_locale):
    """
    Create a new translation of a wiki document.

    * document_slug is for the default locale
    * translation is to the request locale
    """
    # TODO: Refactor this view into two views? (new, edit)
    # That might help reduce the headache-inducing branchiness.

    # The parent document to translate from
    try:
        # Use '.all_objects' because the parent might have been soft deleted.
        # And if we don't respect that fact, it would become impossible to
        # edit a the child of it.
        parent_doc = Document.all_objects.get(
            locale=settings.WIKI_DEFAULT_LANGUAGE, slug=document_slug
        )
    except Document.DoesNotExist:
        raise Http404("Parent document does not exist")

    # Get the mapping here and now so it can be used for input validation
    language_mapping = get_language_mapping()

    # HACK: Seems weird, but sticking the translate-to locale in a query
    # param is the best way to avoid the MindTouch-legacy locale
    # redirection logic.
    document_locale = request.GET.get("tolocale", document_locale)
    if document_locale.lower() not in language_mapping:
        # The 'tolocale' query string parameters aren't free-text. They're
        # explicitly listed on the "Select language" page (`...$locales`)
        # If a locale was entered that wasn't a link it's a user bug.
        raise Http404

    # Set a "Discard Changes" page
    discard_href = ""

    if settings.WIKI_DEFAULT_LANGUAGE == document_locale:
        # Don't translate to the default language.
        return redirect(
            reverse(
                "wiki.edit",
                locale=settings.WIKI_DEFAULT_LANGUAGE,
                args=[parent_doc.slug],
            )
        )

    if not parent_doc.is_localizable:
        message = _("You cannot translate this document.")
        context = {"message": message}
        return render(request, "handlers/400.html", context, status=400)

    based_on_rev = parent_doc.current_or_latest_revision()

    disclose_description = bool(request.GET.get("opendescription"))

    try:
        doc = parent_doc.translations.get(locale=document_locale)
        slug_dict = split_slug(doc.slug)
    except Document.DoesNotExist:
        doc = None
        disclose_description = True
        slug_dict = split_slug(document_slug)

        # Find the "real" parent topic, which is its translation
        if parent_doc.parent_topic:
            try:
                parent_topic_translated_doc = parent_doc.parent_topic.translations.get(
                    locale=document_locale
                )
                slug_dict = split_slug(
                    parent_topic_translated_doc.slug + "/" + slug_dict["specific"]
                )
            except ObjectDoesNotExist:
                pass

    user_has_doc_perm = (not doc) or (doc and doc.allows_editing_by(request.user))

    doc_form = None
    if user_has_doc_perm:
        if doc:
            # If there's an existing doc, populate form from it.
            discard_href = doc.get_absolute_url()
            doc.slug = slug_dict["specific"]
            doc_initial = document_form_initial(doc)
        else:
            # If no existing doc, bring over the original title and slug.
            discard_href = parent_doc.get_absolute_url()
            doc_initial = {"title": based_on_rev.title, "slug": slug_dict["specific"]}
        doc_form = DocumentForm(initial=doc_initial, parent_slug=slug_dict["parent"])

    initial = {
        "based_on": based_on_rev.id,
        "current_rev": doc.current_or_latest_revision().id if doc else None,
        "comment": "",
        "toc_depth": based_on_rev.toc_depth,
        "localization_tags": ["inprogress"],
    }
    content = None
    if not doc:
        content = based_on_rev.content
    if content:
        # TODO: There will be no need to "filterEditorSafety" when the code
        #       that calls "clean_content" on Revision.save is deployed to
        #       production, AND the current revisions of all docs have had
        #       their content cleaned with "clean_content".
        initial.update(
            content=kuma.wiki.content.parse(content).filterEditorSafety().serialize()
        )
    instance = doc and doc.current_or_latest_revision()
    rev_form = RevisionForm(
        request=request,
        instance=instance,
        initial=initial,
        parent_slug=slug_dict["parent"],
    )

    if request.method == "POST":
        which_form = request.POST.get("form-type", "both")
        doc_form_invalid = False

        # Grab the posted slug value in case it's invalid
        posted_slug = request.POST.get("slug", slug_dict["specific"])

        if user_has_doc_perm and which_form in ["doc", "both"]:
            disclose_description = True
            post_data = request.POST.copy()

            post_data.update({"locale": document_locale})

            doc_form = DocumentForm(
                post_data, instance=doc, parent_slug=slug_dict["parent"]
            )
            doc_form.instance.locale = document_locale
            doc_form.instance.parent = parent_doc

            if which_form == "both":
                # Sending a new copy of post so the slug change above
                # doesn't cause problems during validation
                rev_form = RevisionForm(
                    request=request, data=post_data, parent_slug=slug_dict["parent"]
                )

            # If we are submitting the whole form, we need to check that
            # the Revision is valid before saving the Document.
            if doc_form.is_valid() and (which_form == "doc" or rev_form.is_valid()):
                doc = doc_form.save(parent=parent_doc)

                if which_form == "doc":
                    url = urlparams(doc.get_edit_url(), opendescription=1)
                    return redirect(url)
            else:
                doc_form.data["slug"] = posted_slug
                doc_form_invalid = True

        if doc and which_form in ["rev", "both"]:
            post_data = request.POST.copy()
            if "slug" not in post_data:
                post_data["slug"] = posted_slug

            # update the post data with the toc_depth of original
            post_data["toc_depth"] = based_on_rev.toc_depth

            # Pass in the locale for the akistmet "blog_lang".
            post_data["locale"] = document_locale

            rev_form = RevisionForm(
                request=request, data=post_data, parent_slug=slug_dict["parent"]
            )
            rev_form.instance.document = doc  # for rev_form.clean()

            if rev_form.is_valid() and not doc_form_invalid:
                parent_id = request.POST.get("parent_id", "")

                # Attempt to set a parent
                if parent_id:
                    try:
                        try:
                            parent_doc = Document.all_objects.get(id=parent_id)
                        except Document.DoesNotExist:
                            raise Http404("Parent document does not exist")
                        rev_form.instance.document.parent = parent_doc
                        doc.parent = parent_doc
                        rev_form.instance.based_on.document = doc.original
                    except Document.DoesNotExist:
                        pass

                rev_form.save(doc)
                # If this is an Ajax POST, then return a JsonResponse
                if request.is_ajax():
                    data = {
                        "error": False,
                        "new_revision_id": rev_form.instance.id,
                    }

                    return JsonResponse(data)

                # Construct the redirect URL, adding any needed parameters
                url = doc.get_absolute_url()
                params = {}
                # Parameter for the document saved, so that we can delete the cached draft on load
                params["rev_saved"] = request.POST.get("current_rev", "")
                url = "%s?%s" % (url, urlencode(params))
                return redirect(url)
            else:
                # If this is an Ajax POST, then return a JsonResponse with error
                if request.is_ajax():
                    if "current_rev" in rev_form._errors:
                        # Make the error message safe so the '<' and '>' don't
                        # get turned into '&lt;' and '&gt;', respectively
                        rev_form.errors["current_rev"][0] = mark_safe(
                            rev_form.errors["current_rev"][0]
                        )
                    errors = [rev_form.errors[key][0] for key in rev_form.errors.keys()]
                    data = {
                        "error": True,
                        "error_message": errors,
                        "new_revision_id": rev_form.instance.id,
                    }
                    return JsonResponse(data=data)

    if doc:
        from_id = smart_int(request.GET.get("from"), None)
        to_id = smart_int(request.GET.get("to"), None)

        revision_from = get_object_or_none(Revision, pk=from_id, document=doc.parent)
        revision_to = get_object_or_none(Revision, pk=to_id, document=doc.parent)
    else:
        revision_from = revision_to = None

    parent_split = split_slug(parent_doc.slug)

    language = language_mapping[document_locale.lower()]
    default_locale = language_mapping[settings.WIKI_DEFAULT_LANGUAGE.lower()]

    context = {
        "parent": parent_doc,
        "document": doc,
        "document_form": doc_form,
        "revision_form": rev_form,
        "locale": document_locale,
        "default_locale": default_locale,
        "language": language,
        "based_on": based_on_rev,
        "disclose_description": disclose_description,
        "discard_href": discard_href,
        "attachment_form": AttachmentRevisionForm(),
        "specific_slug": parent_split["specific"],
        "parent_slug": parent_split["parent"],
        "revision_from": revision_from,
        "revision_to": revision_to,
    }
    return render(request, "wiki/translate.html", context)
Exemple #7
0
def edit(request, document_slug, document_locale, revision_id=None):
    """Create a new revision of a wiki document, or edit document metadata."""
    doc = get_object_or_404(Document,
                            locale=document_locale,
                            slug=document_slug)
    user = request.user

    # If this document has a parent, then the edit is handled by the
    # translate view. Pass it on.
    if doc.parent and doc.parent.id != doc.id:
        return translate(request,
                         doc.parent.slug,
                         doc.locale,
                         revision_id,
                         bypass_process_document_path=True)
    if revision_id:
        rev = get_object_or_404(Revision, pk=revision_id, document=doc)
    else:
        rev = doc.current_revision or doc.revisions.order_by(
            '-created', '-id')[0]

    # Keep hold of the full post slug
    slug_dict = split_slug(document_slug)
    # Update the slug, removing the parent path, and
    # *only* using the last piece.
    # This is only for the edit form.
    rev.slug = slug_dict['specific']

    section_id = request.GET.get('section', None)
    if section_id and not request.is_ajax():
        return HttpResponse(_("Sections may only be edited inline."))
    disclose_description = bool(request.GET.get('opendescription'))

    doc_form = rev_form = None
    if doc.allows_revision_by(user):
        rev_form = RevisionForm(instance=rev,
                                initial={
                                    'based_on': rev.id,
                                    'current_rev': rev.id,
                                    'comment': ''
                                },
                                section_id=section_id)
    if doc.allows_editing_by(user):
        doc_form = DocumentForm(initial=document_form_initial(doc))

    # Need to make check *here* to see if this could have a translation parent
    show_translation_parent_block = (
        (document_locale != settings.WIKI_DEFAULT_LANGUAGE)
        and (not doc.parent_id))

    if request.method == 'GET':
        if not (rev_form or doc_form):
            # You can't do anything on this page, so get lost.
            raise PermissionDenied

    else:  # POST
        is_iframe_target = request.GET.get('iframe', False)
        is_raw = request.GET.get('raw', False)
        need_edit_links = request.GET.get('edit_links', False)
        parent_id = request.POST.get('parent_id', '')

        # Attempt to set a parent
        if show_translation_parent_block and parent_id:
            try:
                parent_doc = get_object_or_404(Document, id=parent_id)
                doc.parent = parent_doc
            except Document.DoesNotExist:
                pass

        # Comparing against localized names for the Save button bothers me, so
        # I embedded a hidden input:
        which_form = request.POST.get('form')

        if which_form == 'doc':
            if doc.allows_editing_by(user):
                post_data = request.POST.copy()

                post_data.update({'locale': document_locale})
                doc_form = DocumentForm(post_data, instance=doc)
                if doc_form.is_valid():
                    # if must be here for section edits
                    if 'slug' in post_data:
                        post_data['slug'] = join_slug(
                            slug_dict['parent_split'], post_data['slug'])

                    # Get the possibly new slug for the imminent redirection:
                    doc = doc_form.save(None)

                    if is_iframe_target:
                        # TODO: Does this really need to be a template? Just
                        # shoehorning data into a single HTML element.
                        response = HttpResponse("""
                            <span id="iframe-response"
                                  data-status="OK"
                                  data-current-revision="%s">OK</span>
                        """ % doc.current_revision.id)
                        response['X-Frame-Options'] = 'SAMEORIGIN'
                        return response

                    return HttpResponseRedirect(
                        urlparams(reverse('wiki.edit_document',
                                          args=[doc.slug]),
                                  opendescription=1))
                disclose_description = True
            else:
                raise PermissionDenied

        elif which_form == 'rev':
            if not doc.allows_revision_by(user):
                raise PermissionDenied
            else:
                post_data = request.POST.copy()

                rev_form = RevisionForm(post_data,
                                        is_iframe_target=is_iframe_target,
                                        section_id=section_id)
                rev_form.instance.document = doc  # for rev_form.clean()

                # Come up with the original revision to which these changes
                # would be applied.
                orig_rev_id = request.POST.get('current_rev', False)
                if orig_rev_id is False:
                    orig_rev = None
                else:
                    orig_rev = Revision.objects.get(pk=orig_rev_id)
                # Get the document's actual current revision.
                curr_rev = doc.current_revision

                if not rev_form.is_valid():
                    # Was there a mid-air collision?
                    if 'current_rev' in rev_form._errors:
                        # Jump out to a function to escape indentation hell
                        return _edit_document_collision(
                            request, orig_rev, curr_rev, is_iframe_target,
                            is_raw, rev_form, doc_form, section_id, rev, doc)

                if rev_form.is_valid():
                    save_revision_and_notify(rev_form, request, doc)

                    if is_iframe_target:
                        # TODO: Does this really need to be a template? Just
                        # shoehorning data into a single HTML element.
                        response = HttpResponse("""
                            <span id="iframe-response"
                                  data-status="OK"
                                  data-current-revision="%s">OK</span>
                        """ % doc.current_revision.id)
                        response['X-Frame-Options'] = 'SAMEORIGIN'
                        return response

                    if (is_raw and orig_rev is not None
                            and curr_rev.id != orig_rev.id):
                        # If this is the raw view, and there was an original
                        # revision, but the original revision differed from the
                        # current revision at start of editing, we should tell
                        # the client to refresh the page.
                        response = HttpResponse('RESET')
                        response['X-Frame-Options'] = 'SAMEORIGIN'
                        response.status_code = 205
                        return response

                    if rev_form.instance.is_approved:
                        view = 'wiki.document'
                    else:
                        view = 'wiki.document_revisions'

                    # Construct the redirect URL, adding any needed parameters
                    url = reverse(view, args=[doc.slug], locale=doc.locale)
                    params = {}
                    if is_raw:
                        params['raw'] = 'true'
                        if need_edit_links:
                            # Only need to carry over ?edit_links with ?raw,
                            # because they're on by default in the normal UI
                            params['edit_links'] = 'true'
                        if section_id:
                            # If a section was edited, and we're using the raw
                            # content API, constrain to that section.
                            params['section'] = section_id
                    if params:
                        url = '%s?%s' % (url, urlencode(params))
                    if not is_raw and section_id:
                        # If a section was edited, jump to the section anchor
                        # if we're not getting raw content.
                        url = '%s#%s' % (url, section_id)

                    return HttpResponseRedirect(url)

    parent_path = parent_slug = ''
    if slug_dict['parent']:
        parent_slug = slug_dict['parent']

    if doc.parent_topic_id:
        parent_doc = Document.objects.get(pk=doc.parent_topic_id)
        parent_path = parent_doc.get_absolute_url()
        parent_slug = parent_doc.slug

    attachments = attachments_json(doc.attachments)
    allow_add_attachment = (Attachment.objects.allow_add_attachment_by(
        request.user))

    context = {
        'revision_form': rev_form,
        'document_form': doc_form,
        'section_id': section_id,
        'disclose_description': disclose_description,
        'parent_slug': parent_slug,
        'parent_path': parent_path,
        'revision': rev,
        'document': doc,
        'allow_add_attachment': allow_add_attachment,
        'attachment_form': AttachmentRevisionForm(),
        'attachment_data': attachments,
        'WIKI_DOCUMENT_TAG_SUGGESTIONS': config.WIKI_DOCUMENT_TAG_SUGGESTIONS,
        'attachment_data_json': json.dumps(attachments)
    }
    return render(request, 'wiki/edit_document.html', context)
Exemple #8
0
def translate(request, document_slug, document_locale, revision_id=None):
    """
    Create a new translation of a wiki document.

    * document_slug is for the default locale
    * translation is to the request locale
    """
    # TODO: Refactor this view into two views? (new, edit)
    # That might help reduce the headache-inducing branchiness.

    # The parent document to translate from
    parent_doc = get_object_or_404(Document,
                                   locale=settings.WIKI_DEFAULT_LANGUAGE,
                                   slug=document_slug)

    if not revision_id:
        # HACK: Seems weird, but sticking the translate-to locale in a query
        # param is the best way to avoid the MindTouch-legacy locale
        # redirection logic.
        document_locale = request.GET.get('tolocale',
                                          document_locale)

    # Set a "Discard Changes" page
    discard_href = ''

    if settings.WIKI_DEFAULT_LANGUAGE == document_locale:
        # Don't translate to the default language.
        return redirect(reverse(
            'wiki.edit', locale=settings.WIKI_DEFAULT_LANGUAGE,
            args=[parent_doc.slug]))

    if not parent_doc.is_localizable:
        message = _lazy(u'You cannot translate this document.')
        context = {'message': message}
        return render(request, 'handlers/400.html', context, status=400)

    if revision_id:
        revision = get_object_or_404(Revision, pk=revision_id)
    else:
        revision = None

    based_on_rev = parent_doc.current_or_latest_revision()

    disclose_description = bool(request.GET.get('opendescription'))

    try:
        doc = parent_doc.translations.get(locale=document_locale)
        slug_dict = split_slug(doc.slug)
    except Document.DoesNotExist:
        doc = None
        disclose_description = True
        slug_dict = split_slug(document_slug)

        # Find the "real" parent topic, which is its translation
        if parent_doc.parent_topic:
            try:
                parent_topic_translated_doc = (parent_doc.parent_topic
                                                         .translations
                                                         .get(locale=document_locale))
                slug_dict = split_slug(parent_topic_translated_doc.slug +
                                       '/' +
                                       slug_dict['specific'])
            except ObjectDoesNotExist:
                pass

    user_has_doc_perm = (not doc) or (doc and doc.allows_editing_by(request.user))
    user_has_rev_perm = (not doc) or (doc and doc.allows_revision_by(request.user))
    if not user_has_doc_perm and not user_has_rev_perm:
        # User has no perms, bye.
        raise PermissionDenied

    doc_form = rev_form = None

    if user_has_doc_perm:
        if doc:
            # If there's an existing doc, populate form from it.
            discard_href = doc.get_absolute_url()
            doc.slug = slug_dict['specific']
            doc_initial = document_form_initial(doc)
        else:
            # If no existing doc, bring over the original title and slug.
            discard_href = parent_doc.get_absolute_url()
            doc_initial = {'title': based_on_rev.title,
                           'slug': slug_dict['specific']}
        doc_form = DocumentForm(initial=doc_initial,
                                parent_slug=slug_dict['parent'])

    if user_has_rev_perm:
        initial = {
            'based_on': based_on_rev.id,
            'comment': '',
            'toc_depth': based_on_rev.toc_depth,
            'localization_tags': ['inprogress'],
        }
        content = None
        if revision is not None:
            content = revision.content
        elif not doc:
            content = based_on_rev.content
        if content:
            initial.update(content=kuma.wiki.content.parse(content)
                                                    .filterEditorSafety()
                                                    .serialize())
        instance = doc and doc.current_or_latest_revision()
        rev_form = RevisionForm(request=request,
                                instance=instance,
                                initial=initial,
                                parent_slug=slug_dict['parent'])

    if request.method == 'POST':
        which_form = request.POST.get('form', 'both')
        doc_form_invalid = False

        # Grab the posted slug value in case it's invalid
        posted_slug = request.POST.get('slug', slug_dict['specific'])

        if user_has_doc_perm and which_form in ['doc', 'both']:
            disclose_description = True
            post_data = request.POST.copy()

            post_data.update({'locale': document_locale})

            doc_form = DocumentForm(post_data, instance=doc,
                                    parent_slug=slug_dict['parent'])
            doc_form.instance.locale = document_locale
            doc_form.instance.parent = parent_doc

            if which_form == 'both':
                # Sending a new copy of post so the slug change above
                # doesn't cause problems during validation
                rev_form = RevisionForm(request=request,
                                        data=request.POST,
                                        parent_slug=slug_dict['parent'])

            # If we are submitting the whole form, we need to check that
            # the Revision is valid before saving the Document.
            if doc_form.is_valid() and (which_form == 'doc' or
                                        rev_form.is_valid()):
                doc = doc_form.save(parent=parent_doc)

                if which_form == 'doc':
                    url = urlparams(doc.get_edit_url(), opendescription=1)
                    return redirect(url)
            else:
                doc_form.data['slug'] = posted_slug
                doc_form_invalid = True

        if doc and user_has_rev_perm and which_form in ['rev', 'both']:
            post_data = request.POST.copy()
            if 'slug' not in post_data:
                post_data['slug'] = posted_slug

            # update the post data with the toc_depth of original
            post_data['toc_depth'] = based_on_rev.toc_depth

            rev_form = RevisionForm(request=request,
                                    data=post_data,
                                    parent_slug=slug_dict['parent'])
            rev_form.instance.document = doc  # for rev_form.clean()

            if rev_form.is_valid() and not doc_form_invalid:
                parent_id = request.POST.get('parent_id', '')

                # Attempt to set a parent
                if parent_id:
                    try:
                        parent_doc = get_object_or_404(Document, id=parent_id)
                        rev_form.instance.document.parent = parent_doc
                        doc.parent = parent_doc
                        rev_form.instance.based_on.document = doc.original
                    except Document.DoesNotExist:
                        pass

                rev_form.save(doc)
                return redirect(doc)

    if doc:
        from_id = smart_int(request.GET.get('from'), None)
        to_id = smart_int(request.GET.get('to'), None)

        revision_from = get_object_or_none(Revision,
                                           pk=from_id,
                                           document=doc.parent)
        revision_to = get_object_or_none(Revision,
                                         pk=to_id,
                                         document=doc.parent)
    else:
        revision_from = revision_to = None

    parent_split = split_slug(parent_doc.slug)

    language_mapping = get_language_mapping()
    language = language_mapping[document_locale.lower()]
    default_locale = language_mapping[settings.WIKI_DEFAULT_LANGUAGE.lower()]

    context = {
        'parent': parent_doc,
        'document': doc,
        'document_form': doc_form,
        'revision_form': rev_form,
        'locale': document_locale,
        'default_locale': default_locale,
        'language': language,
        'based_on': based_on_rev,
        'disclose_description': disclose_description,
        'discard_href': discard_href,
        'attachment_form': AttachmentRevisionForm(),
        'specific_slug': parent_split['specific'],
        'parent_slug': parent_split['parent'],
        'revision_from': revision_from,
        'revision_to': revision_to,
    }
    return render(request, 'wiki/translate.html', context)
Exemple #9
0
def new_document(request):
    """Create a new wiki document."""

    initial_slug = request.GET.get('slug', '')
    initial_title = initial_slug.replace('_', ' ')

    initial_parent_id = ''
    try:
        initial_parent_id = int(request.GET.get('parent', ''))
    except ValueError:
        pass

    clone_id = None
    try:
        clone_id = int(request.GET.get('clone', ''))
    except ValueError:
        pass

    if not Document.objects.allows_add_by(request.user, initial_slug):
        # Try to head off disallowed Template:* creation, right off the bat
        raise PermissionDenied

    is_template = initial_slug.startswith(TEMPLATE_TITLE_PREFIX)

    # If a parent ID is provided via GET, confirm it exists
    parent_slug = parent_path = ''

    if initial_parent_id:
        try:
            parent_doc = Document.objects.get(pk=initial_parent_id)
            parent_slug = parent_doc.slug
            parent_path = parent_doc.get_absolute_url()
        except Document.DoesNotExist:
            pass

    if request.method == 'GET':

        initial_data = {}
        initial_html = ''
        initial_tags = ''
        initial_toc = Revision.TOC_DEPTH_H4

        if clone_id:
            try:
                clone_doc = Document.objects.get(pk=clone_id)
                initial_title = clone_doc.title
                initial_html = clone_doc.html
                initial_tags = clone_doc.tags.all()
                if clone_doc.current_revision:
                    initial_toc = clone_doc.current_revision.toc_depth
                else:
                    initial_toc = 1

            except Document.DoesNotExist:
                pass

        if parent_slug:
            initial_data['parent_topic'] = initial_parent_id

        if initial_slug:
            initial_data['title'] = initial_title
            initial_data['slug'] = initial_slug

        if is_template:
            review_tags = ('template',)
        else:
            review_tags = REVIEW_FLAG_TAGS_DEFAULT

        doc_form = DocumentForm(initial=initial_data)

        rev_form = RevisionForm(initial={
            'slug': initial_slug,
            'title': initial_title,
            'content': initial_html,
            'review_tags': review_tags,
            'tags': initial_tags,
            'toc_depth': initial_toc
        })

        allow_add_attachment = (
            Attachment.objects.allow_add_attachment_by(request.user))
        context = {
            'is_template': is_template,
            'parent_slug': parent_slug,
            'parent_id': initial_parent_id,
            'document_form': doc_form,
            'revision_form': rev_form,
            'WIKI_DOCUMENT_TAG_SUGGESTIONS': config.WIKI_DOCUMENT_TAG_SUGGESTIONS,
            'initial_tags': initial_tags,
            'allow_add_attachment': allow_add_attachment,
            'attachment_form': AttachmentRevisionForm(),
            'parent_path': parent_path}

        return render(request, 'wiki/new_document.html', context)

    post_data = request.POST.copy()
    posted_slug = post_data['slug']
    post_data.update({'locale': request.locale})
    if parent_slug:
        post_data.update({'parent_topic': initial_parent_id})
        post_data.update({'slug': parent_slug + '/' + post_data['slug']})

    doc_form = DocumentForm(post_data)
    rev_form = RevisionValidationForm(request.POST.copy())
    rev_form.parent_slug = parent_slug

    if doc_form.is_valid() and rev_form.is_valid():
        rev_form = RevisionForm(post_data)
        if rev_form.is_valid():
            slug = doc_form.cleaned_data['slug']
            if not Document.objects.allows_add_by(request.user, slug):
                raise PermissionDenied

            doc = doc_form.save(None)
            save_revision_and_notify(rev_form, request, doc)
            if doc.current_revision.is_approved:
                view = 'wiki.document'
            else:
                view = 'wiki.document_revisions'
            return HttpResponseRedirect(reverse(view, args=[doc.slug]))
        else:
            doc_form.data['slug'] = posted_slug
    else:
        doc_form.data['slug'] = posted_slug

    allow_add_attachment = (
        Attachment.objects.allow_add_attachment_by(request.user))

    context = {
        'is_template': is_template,
        'document_form': doc_form,
        'revision_form': rev_form,
        'WIKI_DOCUMENT_TAG_SUGGESTIONS': config.WIKI_DOCUMENT_TAG_SUGGESTIONS,
        'allow_add_attachment': allow_add_attachment,
        'attachment_form': AttachmentRevisionForm(),
        'parent_slug': parent_slug,
        'parent_path': parent_path,
    }
    return render(request, 'wiki/new_document.html', context)