Example #1
0
def upload_async(request, media_type='image'):
    """Upload images or videos from request.FILES."""
    # TODO(paul): validate the Submit File on upload modal async
    #             even better, use JS validation for title length.
    try:
        if media_type == 'image':
            file_info = upload_image(request)
        else:
            file_info = upload_video(request)
    except FileTooLargeError as e:
        return HttpResponseBadRequest(
            json.dumps({
                'status': 'error',
                'message': e.args[0]
            }))

    if isinstance(file_info, dict) and 'thumbnail_url' in file_info:
        schedule_rebuild_kb()
        return HttpResponse(
            json.dumps({
                'status': 'success',
                'file': file_info
            }))

    message = MSG_FAIL_UPLOAD[media_type]
    return HttpResponseBadRequest(
        json.dumps({
            'status': 'error',
            'message': unicode(message),
            'errors': file_info
        }))
Example #2
0
def review_revision(request, document_slug, revision_id):
    """Review a revision of a wiki document."""
    rev = get_object_or_404(Revision,
                            pk=revision_id,
                            document__slug=document_slug)
    doc = rev.document
    form = ReviewForm()

    if request.method == 'POST':
        form = ReviewForm(request.POST)
        if form.is_valid() and not rev.reviewed:
            # Don't allow revisions to be reviewed twice
            rev.is_approved = 'approve' in request.POST
            rev.reviewer = request.user
            rev.reviewed = datetime.now()
            if form.cleaned_data['significance']:
                rev.significance = form.cleaned_data['significance']
            rev.save()

            # Send an email (not really a "notification" in the sense that
            # there's a Watch table entry) to revision creator.
            msg = form.cleaned_data['comment']
            send_reviewed_notification.delay(rev, doc, msg)

            # If approved, send approved notification
            ApproveRevisionInLocaleEvent(rev).fire(exclude=rev.creator)

            # Schedule KB rebuild?
            schedule_rebuild_kb()

            return HttpResponseRedirect(
                reverse('wiki.document_revisions', args=[document_slug]))

    if doc.parent:  # A translation
        parent_revision = get_current_or_latest_revision(doc.parent)
        template = 'wiki/review_translation.html'
    else:
        parent_revision = None
        template = 'wiki/review_revision.html'

    data = {
        'revision': rev,
        'document': doc,
        'form': form,
        'parent_revision': parent_revision
    }
    data.update(SHOWFOR_DATA)
    return jingo.render(request, template, data)
Example #3
0
def review_revision(request, document_slug, revision_id):
    """Review a revision of a wiki document."""
    rev = get_object_or_404(Revision, pk=revision_id,
                            document__slug=document_slug)
    doc = rev.document
    form = ReviewForm()

    # Don't ask significance if this doc is a translation or if it has no
    # former approved versions:
    should_ask_significance = not doc.parent and doc.current_revision

    if request.method == 'POST':
        form = ReviewForm(request.POST)
        if form.is_valid() and not rev.reviewed:
            # Don't allow revisions to be reviewed twice
            rev.is_approved = 'approve' in request.POST
            rev.reviewer = request.user
            rev.reviewed = datetime.now()
            if should_ask_significance and form.cleaned_data['significance']:
                rev.significance = form.cleaned_data['significance']
            rev.save()

            # Send an email (not really a "notification" in the sense that
            # there's a Watch table entry) to revision creator.
            msg = form.cleaned_data['comment']
            send_reviewed_notification.delay(rev, doc, msg)

            # If approved, send approved notification
            ApproveRevisionInLocaleEvent(rev).fire(exclude=rev.creator)

            # Schedule KB rebuild?
            schedule_rebuild_kb()

            return HttpResponseRedirect(reverse('wiki.document_revisions',
                                                args=[document_slug]))

    if doc.parent:  # A translation
        parent_revision = get_current_or_latest_revision(doc.parent)
        template = 'wiki/review_translation.html'
    else:
        parent_revision = None
        template = 'wiki/review_revision.html'

    data = {'revision': rev, 'document': doc, 'form': form,
            'parent_revision': parent_revision,
            'should_ask_significance': should_ask_significance}
    data.update(SHOWFOR_DATA)
    return jingo.render(request, template, data)
Example #4
0
def upload_async(request, media_type="image"):
    """Upload images or videos from request.FILES."""
    # TODO(paul): validate the Submit File on upload modal async
    #             even better, use JS validation for title length.
    try:
        if media_type == "image":
            file_info = upload_image(request)
        else:
            file_info = upload_video(request)
    except FileTooLargeError as e:
        return HttpResponseBadRequest(json.dumps({"status": "error", "message": e.args[0]}))

    if isinstance(file_info, dict) and "thumbnail_url" in file_info:
        schedule_rebuild_kb()
        return HttpResponse(json.dumps({"status": "success", "file": file_info}))

    message = MSG_FAIL_UPLOAD[media_type]
    return HttpResponseBadRequest(json.dumps({"status": "error", "message": unicode(message), "errors": file_info}))
Example #5
0
def delete_media(request, media_id, media_type='image'):
    """Delete media and redirect to gallery view."""
    media, media_format = _get_media_info(media_id, media_type)

    check_media_permissions(media, request.user, 'delete')

    if request.method == 'GET':
        # Render the confirmation page
        return jingo.render(request, 'gallery/confirm_media_delete.html',
                            {'media': media, 'media_type': media_type,
                             'media_format': media_format})

    # Handle confirm delete form POST
    log.warning('User %s is deleting %s with id=%s' %
                (request.user, media_type, media.id))
    media.delete()
    # Rebuild KB
    schedule_rebuild_kb()
    return HttpResponseRedirect(reverse('gallery.gallery', args=[media_type]))
Example #6
0
def delete_media(request, media_id, media_type="image"):
    """Delete media and redirect to gallery view."""
    media, media_format = _get_media_info(media_id, media_type)

    check_media_permissions(media, request.user, "delete")

    if request.method == "GET":
        # Render the confirmation page
        return jingo.render(
            request,
            "gallery/confirm_media_delete.html",
            {"media": media, "media_type": media_type, "media_format": media_format},
        )

    # Handle confirm delete form POST
    log.warning("User %s is deleting %s with id=%s" % (request.user, media_type, media.id))
    media.delete()
    # Rebuild KB
    schedule_rebuild_kb()
    return HttpResponseRedirect(reverse("gallery.gallery", args=[media_type]))
Example #7
0
def upload(request, media_type='image'):
    """Finalizes an uploaded draft."""
    drafts = _get_drafts(request.user)
    if media_type == 'image' and drafts['image']:
        # We're publishing an image draft!
        image_form = _init_media_form(ImageForm, request, drafts['image'][0])
        if image_form.is_valid():
            img = image_form.save(is_draft=None)
            generate_thumbnail.delay(img, 'file', 'thumbnail')
            compress_image.delay(img, 'file')
            # TODO: We can drop this when we start using Redis.
            invalidate = Image.objects.exclude(pk=img.pk)
            if invalidate.exists():
                Image.objects.invalidate(invalidate[0])
            # Rebuild KB
            schedule_rebuild_kb()
            return HttpResponseRedirect(img.get_absolute_url())
        else:
            return gallery(request, media_type='image')
    elif media_type == 'video' and drafts['video']:
        # We're publishing a video draft!
        video_form = _init_media_form(VideoForm, request, drafts['video'][0])
        if video_form.is_valid():
            vid = video_form.save(is_draft=None)
            if vid.thumbnail:
                generate_thumbnail.delay(vid,
                                         'poster',
                                         'poster',
                                         max_size=settings.WIKI_VIDEO_WIDTH)
                generate_thumbnail.delay(vid, 'thumbnail', 'thumbnail')
            # TODO: We can drop this when we start using Redis.
            invalidate = Video.objects.exclude(pk=vid.pk)
            if invalidate.exists():
                Video.objects.invalidate(invalidate[0])
            # Rebuild KB
            schedule_rebuild_kb()
            return HttpResponseRedirect(vid.get_absolute_url())
        else:
            return gallery(request, media_type='video')

    return HttpResponseBadRequest(u'Unrecognized POST request.')
Example #8
0
def delete_media(request, media_id, media_type='image'):
    """Delete media and redirect to gallery view."""
    media, media_format = _get_media_info(media_id, media_type)

    check_media_permissions(media, request.user, 'delete')

    if request.method == 'GET':
        # Render the confirmation page
        return jingo.render(request, 'gallery/confirm_media_delete.html', {
            'media': media,
            'media_type': media_type,
            'media_format': media_format
        })

    # Handle confirm delete form POST
    log.warning('User %s is deleting %s with id=%s' %
                (request.user, media_type, media.id))
    media.delete()
    # Rebuild KB
    schedule_rebuild_kb()
    return HttpResponseRedirect(reverse('gallery.gallery', args=[media_type]))
Example #9
0
def review_revision(request, document_slug, revision_id):
    """Review a revision of a wiki document."""
    rev = get_object_or_404(Revision, pk=revision_id,
                            document__slug=document_slug)
    doc = rev.document
    form = ReviewForm()

    if request.method == 'POST':
        form = ReviewForm(request.POST)
        if form.is_valid() and not rev.reviewed:
            # Don't allow revisions to be reviewed twice
            rev.is_approved = 'approve' in request.POST
            rev.reviewer = request.user
            rev.reviewed = datetime.now()
            if form.cleaned_data['significance']:
                rev.significance = form.cleaned_data['significance']
            rev.save()

            # Send notification to revision creator.
            msg = form.cleaned_data['comment']
            send_reviewed_notification.delay(rev, doc, msg)

            # If approved, send approved notification
            send_approved_notification.delay(rev, doc)

            # Schedule KB rebuild?
            schedule_rebuild_kb()

            return HttpResponseRedirect(reverse('wiki.document_revisions',
                                                args=[document_slug]))

    if doc.parent:  # A translation
        template = 'wiki/review_translation.html'
    else:
        template = 'wiki/review_revision.html'

    data = {'revision': rev, 'document': doc, 'form': form}
    data.update(SHOWFOR_DATA)
    return jingo.render(request, template, data)
Example #10
0
def upload(request, media_type='image'):
    """Finalizes an uploaded draft."""
    drafts = _get_drafts(request.user)
    if media_type == 'image' and drafts['image']:
        # We're publishing an image draft!
        image_form = _init_media_form(ImageForm, request, drafts['image'][0])
        if image_form.is_valid():
            img = image_form.save(is_draft=None)
            generate_thumbnail.delay(img, 'file', 'thumbnail')
            compress_image.delay(img, 'file')
            # TODO: We can drop this when we start using Redis.
            invalidate = Image.objects.exclude(pk=img.pk)
            if invalidate.exists():
                Image.objects.invalidate(invalidate[0])
            # Rebuild KB
            schedule_rebuild_kb()
            return HttpResponseRedirect(img.get_absolute_url())
        else:
            return gallery(request, media_type='image')
    elif media_type == 'video' and drafts['video']:
        # We're publishing a video draft!
        video_form = _init_media_form(VideoForm, request, drafts['video'][0])
        if video_form.is_valid():
            vid = video_form.save(is_draft=None)
            if vid.thumbnail:
                generate_thumbnail.delay(vid, 'poster', 'poster',
                                         max_size=settings.WIKI_VIDEO_WIDTH)
                generate_thumbnail.delay(vid, 'thumbnail', 'thumbnail')
            # TODO: We can drop this when we start using Redis.
            invalidate = Video.objects.exclude(pk=vid.pk)
            if invalidate.exists():
                Video.objects.invalidate(invalidate[0])
            # Rebuild KB
            schedule_rebuild_kb()
            return HttpResponseRedirect(vid.get_absolute_url())
        else:
            return gallery(request, media_type='video')

    return HttpResponseBadRequest(u'Unrecognized POST request.')
Example #11
0
 def test_dont_queue(self, get, delay):
     settings.WIKI_REBUILD_ON_DEMAND = False
     schedule_rebuild_kb()
     assert not get.called
     assert not delay.called
Example #12
0
 def test_task_queue(self, delay):
     celery.conf.ALWAYS_EAGER = False
     schedule_rebuild_kb()
     assert cache.get(settings.WIKI_REBUILD_TOKEN)
     assert delay.called
Example #13
0
 def test_already_queued(self, delay):
     cache.set(settings.WIKI_REBUILD_TOKEN, True)
     schedule_rebuild_kb()
     assert cache.get(settings.WIKI_REBUILD_TOKEN)
     assert not delay.called
Example #14
0
def _maybe_schedule_rebuild(form):
    """Try to schedule a KB rebuild if a title or slug has changed."""
    if 'title' in form.changed_data or 'slug' in form.changed_data:
        schedule_rebuild_kb()
Example #15
0
 def test_eager_queue(self, delay):
     schedule_rebuild_kb()
     assert not cache.get(settings.WIKI_REBUILD_TOKEN)
     assert not delay.called
Example #16
0
 def test_eager_queue(self, switch_is_active, delay):
     switch_is_active.return_value = True
     schedule_rebuild_kb()
     assert not cache.get(settings.WIKI_REBUILD_TOKEN)
     assert not delay.called
Example #17
0
def review_revision(request, document_slug, revision_id):
    """Review a revision of a wiki document."""
    rev = get_object_or_404(Revision, pk=revision_id,
                            document__slug=document_slug)
    doc = rev.document
    form = ReviewForm()

    # Don't ask significance if this doc is a translation or if it has no
    # former approved versions:
    should_ask_significance = not doc.parent and doc.current_revision

    if request.method == 'POST':
        form = ReviewForm(request.POST)
        if form.is_valid() and not rev.reviewed:
            # Don't allow revisions to be reviewed twice
            rev.is_approved = 'approve' in request.POST
            rev.reviewer = request.user
            rev.reviewed = datetime.now()
            if should_ask_significance and form.cleaned_data['significance']:
                rev.significance = form.cleaned_data['significance']

            # If document is localizable and revision was approved and
            # user has permission, set the is_ready_for_localization value.
            if (doc.is_localizable and rev.is_approved and
                request.user.has_perm('wiki.mark_ready_for_l10n')):
                rev.is_ready_for_localization = form.cleaned_data[
                    'is_ready_for_localization']

            rev.save()

            # Send notifications of approvedness and readiness:
            if rev.is_ready_for_localization or rev.is_approved:
                events = [ApproveRevisionInLocaleEvent(rev)]
                if rev.is_ready_for_localization:
                    events.append(ReadyRevisionEvent(rev))
                ApprovedOrReadyUnion(*events).fire(exclude=[rev.creator,
                                                            request.user])

            # Send an email (not really a "notification" in the sense that
            # there's a Watch table entry) to revision creator.
            msg = form.cleaned_data['comment']
            send_reviewed_notification.delay(rev, doc, msg)

            # Schedule KB rebuild?
            statsd.incr('wiki.review')
            schedule_rebuild_kb()

            return HttpResponseRedirect(reverse('wiki.document_revisions',
                                                args=[document_slug]))

    if doc.parent:  # A translation
        # For diffing the based_on revision against, to help the user see if he
        # translated all the recent changes:
        parent_revision = doc.parent.localizable_or_latest_revision()
        template = 'wiki/review_translation.html'
    else:
        parent_revision = None
        template = 'wiki/review_revision.html'

    data = {'revision': rev, 'document': doc, 'form': form,
            'parent_revision': parent_revision,
            'should_ask_significance': should_ask_significance}
    data.update(SHOWFOR_DATA)
    return jingo.render(request, template, data)
Example #18
0
def review_revision(request, document_slug, revision_id):
    """Review a revision of a wiki document."""
    rev = get_object_or_404(Revision, pk=revision_id,
                            document__slug=document_slug)
    doc = rev.document
    form = ReviewForm(
        initial={'needs_change': doc.needs_change,
                 'needs_change_comment': doc.needs_change_comment})

    # Don't ask significance if this doc is a translation or if it has no
    # former approved versions:
    should_ask_significance = not doc.parent and doc.current_revision

    based_on_revs = doc.revisions.all()
    last_approved_date = getattr(doc.current_revision, 'created',
                                   datetime.fromordinal(1))
    based_on_revs = based_on_revs.filter(created__gt=last_approved_date)
    revision_contributors = list(set(
        based_on_revs.values_list('creator__username', flat=True)))

    # Don't include the reviewer in the recent contributors list.
    if request.user.username in revision_contributors:
        revision_contributors.remove(request.user.username)

    if request.method == 'POST':
        form = ReviewForm(request.POST)
        if form.is_valid() and not rev.reviewed:
            # Don't allow revisions to be reviewed twice
            rev.is_approved = 'approve' in request.POST
            rev.reviewer = request.user
            rev.reviewed = datetime.now()
            if should_ask_significance and form.cleaned_data['significance']:
                rev.significance = form.cleaned_data['significance']

            # If document is localizable and revision was approved and
            # user has permission, set the is_ready_for_localization value.
            if (doc.is_localizable and rev.is_approved and
                request.user.has_perm('wiki.mark_ready_for_l10n')):
                rev.is_ready_for_localization = form.cleaned_data[
                    'is_ready_for_localization']

                # If the revision is ready for l10n, store the date
                # and the user.
                if rev.is_ready_for_localization:
                    rev.readied_for_localization = rev.reviewed
                    rev.readied_for_localization_by = rev.reviewer

            rev.save()

            # Update the needs change bit (if approved, default language and
            # user has permission).
            if (doc.locale == settings.WIKI_DEFAULT_LANGUAGE and
                doc.allows_editing_by(request.user) and rev.is_approved):
                doc.needs_change = form.cleaned_data['needs_change']
                doc.needs_change_comment = \
                    form.cleaned_data['needs_change_comment']
                doc.save()

            # Send notifications of approvedness and readiness:
            if rev.is_ready_for_localization or rev.is_approved:
                events = [ApproveRevisionInLocaleEvent(rev)]
                if rev.is_ready_for_localization:
                    events.append(ReadyRevisionEvent(rev))
                ApprovedOrReadyUnion(*events).fire(exclude=[rev.creator,
                                                            request.user])

            # Send an email (not really a "notification" in the sense that
            # there's a Watch table entry) to revision creator.
            msg = form.cleaned_data['comment']
            send_reviewed_notification.delay(rev, doc, msg)
            send_contributor_notification(based_on_revs, rev, doc, msg)

            # Schedule KB rebuild?
            statsd.incr('wiki.review')
            schedule_rebuild_kb()

            return HttpResponseRedirect(reverse('wiki.document_revisions',
                                                args=[document_slug]))

    if doc.parent:  # A translation
        # For diffing the based_on revision against, to help the user see if he
        # translated all the recent changes:
        parent_revision = (rev.based_on or
                           doc.parent.localizable_or_latest_revision())
        template = 'wiki/review_translation.html'
    else:
        parent_revision = None
        template = 'wiki/review_revision.html'

    data = {'revision': rev, 'document': doc, 'form': form,
            'parent_revision': parent_revision,
            'revision_contributors': list(revision_contributors),
            'should_ask_significance': should_ask_significance}
    data.update(showfor_data())
    return render(request, template, data)
Example #19
0
 def test_dont_queue(self, switch_is_active, get, delay):
     switch_is_active.return_value = False
     schedule_rebuild_kb()
     assert not get.called
     assert not delay.called
Example #20
0
 def test_already_queued(self, delay):
     cache.set(settings.WIKI_REBUILD_TOKEN, True)
     schedule_rebuild_kb()
     assert cache.get(settings.WIKI_REBUILD_TOKEN)
     assert not delay.called
Example #21
0
 def test_eager_queue(self, switch_is_active, delay):
     switch_is_active.return_value = True
     schedule_rebuild_kb()
     assert not cache.get(settings.WIKI_REBUILD_TOKEN)
     assert not delay.called
Example #22
0
 def test_eager_queue(self, delay):
     schedule_rebuild_kb()
     assert not cache.get(settings.WIKI_REBUILD_TOKEN)
     assert not delay.called
Example #23
0
 def test_already_queued(self, switch_is_active, delay):
     switch_is_active.return_value = True
     cache.set(settings.WIKI_REBUILD_TOKEN, True)
     schedule_rebuild_kb()
     assert cache.get(settings.WIKI_REBUILD_TOKEN)
     assert not delay.called
Example #24
0
 def test_task_queue(self, switch_is_active, delay):
     switch_is_active.return_value = True
     celery.conf.ALWAYS_EAGER = False
     schedule_rebuild_kb()
     assert cache.get(settings.WIKI_REBUILD_TOKEN)
     assert delay.called
Example #25
0
 def test_task_queue(self, switch_is_active, delay):
     switch_is_active.return_value = True
     celery.conf.ALWAYS_EAGER = False
     schedule_rebuild_kb()
     assert cache.get(settings.WIKI_REBUILD_TOKEN)
     assert delay.called
Example #26
0
 def test_already_queued(self, switch_is_active, delay):
     switch_is_active.return_value = True
     cache.set(settings.WIKI_REBUILD_TOKEN, True)
     schedule_rebuild_kb()
     assert cache.get(settings.WIKI_REBUILD_TOKEN)
     assert not delay.called
Example #27
0
 def test_dont_queue(self, switch_is_active, get, delay):
     switch_is_active.return_value = False
     schedule_rebuild_kb()
     assert not get.called
     assert not delay.called
Example #28
0
def review_revision(request, document_slug, revision_id):
    """Review a revision of a wiki document."""
    rev = get_object_or_404(Revision, pk=revision_id, document__slug=document_slug)
    doc = rev.document
    form = ReviewForm(initial={"needs_change": doc.needs_change, "needs_change_comment": doc.needs_change_comment})

    # Don't ask significance if this doc is a translation or if it has no
    # former approved versions:
    should_ask_significance = not doc.parent and doc.current_revision

    based_on_revs = doc.revisions.all()
    last_approved_date = getattr(doc.current_revision, "created", datetime.fromordinal(1))
    based_on_revs = based_on_revs.filter(created__gt=last_approved_date)
    recent_contributors = based_on_revs.values_list("creator__username", flat=True)

    if request.method == "POST":
        form = ReviewForm(request.POST)
        if form.is_valid() and not rev.reviewed:
            # Don't allow revisions to be reviewed twice
            rev.is_approved = "approve" in request.POST
            rev.reviewer = request.user
            rev.reviewed = datetime.now()
            if should_ask_significance and form.cleaned_data["significance"]:
                rev.significance = form.cleaned_data["significance"]

            # If document is localizable and revision was approved and
            # user has permission, set the is_ready_for_localization value.
            if doc.is_localizable and rev.is_approved and request.user.has_perm("wiki.mark_ready_for_l10n"):
                rev.is_ready_for_localization = form.cleaned_data["is_ready_for_localization"]

            rev.save()

            # Update the needs change bit (if approved, default language and
            # user has permission).
            if doc.locale == settings.WIKI_DEFAULT_LANGUAGE and doc.allows_editing_by(request.user) and rev.is_approved:
                doc.needs_change = form.cleaned_data["needs_change"]
                doc.needs_change_comment = form.cleaned_data["needs_change_comment"]
                doc.save()

            # Send notifications of approvedness and readiness:
            if rev.is_ready_for_localization or rev.is_approved:
                events = [ApproveRevisionInLocaleEvent(rev)]
                if rev.is_ready_for_localization:
                    events.append(ReadyRevisionEvent(rev))
                ApprovedOrReadyUnion(*events).fire(exclude=[rev.creator, request.user])

            # Send an email (not really a "notification" in the sense that
            # there's a Watch table entry) to revision creator.
            msg = form.cleaned_data["comment"]
            send_reviewed_notification.delay(rev, doc, msg)
            send_contributor_notification(based_on_revs, rev, doc, msg)

            # Schedule KB rebuild?
            statsd.incr("wiki.review")
            schedule_rebuild_kb()

            return HttpResponseRedirect(reverse("wiki.document_revisions", args=[document_slug]))

    if doc.parent:  # A translation
        # For diffing the based_on revision against, to help the user see if he
        # translated all the recent changes:
        parent_revision = doc.parent.localizable_or_latest_revision()
        template = "wiki/review_translation.html"
    else:
        parent_revision = None
        template = "wiki/review_revision.html"

    data = {
        "revision": rev,
        "document": doc,
        "form": form,
        "parent_revision": parent_revision,
        "recent_contributors": list(recent_contributors),
        "should_ask_significance": should_ask_significance,
    }
    data.update(SHOWFOR_DATA)
    return jingo.render(request, template, data)
Example #29
0
 def test_task_queue(self, delay):
     celery.conf.ALWAYS_EAGER = False
     schedule_rebuild_kb()
     assert cache.get(settings.WIKI_REBUILD_TOKEN)
     assert delay.called
Example #30
0
def _maybe_schedule_rebuild(form):
    """Try to schedule a KB rebuild if a title or slug has changed."""
    if 'title' in form.changed_data or 'slug' in form.changed_data:
        schedule_rebuild_kb()
Example #31
0
 def test_dont_queue(self, get, delay):
     settings.WIKI_REBUILD_ON_DEMAND = False
     schedule_rebuild_kb()
     assert not get.called
     assert not delay.called
Example #32
0
def review_revision(request, document_slug, revision_id):
    """Review a revision of a wiki document."""
    rev = get_object_or_404(Revision,
                            pk=revision_id,
                            document__slug=document_slug)
    doc = rev.document
    form = ReviewForm(
        initial={
            'needs_change': doc.needs_change,
            'needs_change_comment': doc.needs_change_comment
        })

    # Don't ask significance if this doc is a translation or if it has no
    # former approved versions:
    should_ask_significance = not doc.parent and doc.current_revision

    based_on_revs = doc.revisions.all()
    last_approved_date = getattr(doc.current_revision, 'created',
                                 datetime.fromordinal(1))
    based_on_revs = based_on_revs.filter(created__gt=last_approved_date)
    revision_contributors = list(
        set(based_on_revs.values_list('creator__username', flat=True)))

    # Don't include the reviewer in the recent contributors list.
    if request.user.username in revision_contributors:
        revision_contributors.remove(request.user.username)

    if request.method == 'POST':
        form = ReviewForm(request.POST)
        if form.is_valid() and not rev.reviewed:
            # Don't allow revisions to be reviewed twice
            rev.is_approved = 'approve' in request.POST
            rev.reviewer = request.user
            rev.reviewed = datetime.now()
            if should_ask_significance and form.cleaned_data['significance']:
                rev.significance = form.cleaned_data['significance']

            # If document is localizable and revision was approved and
            # user has permission, set the is_ready_for_localization value.
            if (doc.is_localizable and rev.is_approved
                    and request.user.has_perm('wiki.mark_ready_for_l10n')):
                rev.is_ready_for_localization = form.cleaned_data[
                    'is_ready_for_localization']

            rev.save()

            # Update the needs change bit (if approved, default language and
            # user has permission).
            if (doc.locale == settings.WIKI_DEFAULT_LANGUAGE
                    and doc.allows_editing_by(request.user)
                    and rev.is_approved):
                doc.needs_change = form.cleaned_data['needs_change']
                doc.needs_change_comment = \
                    form.cleaned_data['needs_change_comment']
                doc.save()

            # Send notifications of approvedness and readiness:
            if rev.is_ready_for_localization or rev.is_approved:
                events = [ApproveRevisionInLocaleEvent(rev)]
                if rev.is_ready_for_localization:
                    events.append(ReadyRevisionEvent(rev))
                ApprovedOrReadyUnion(*events).fire(
                    exclude=[rev.creator, request.user])

            # Send an email (not really a "notification" in the sense that
            # there's a Watch table entry) to revision creator.
            msg = form.cleaned_data['comment']
            send_reviewed_notification.delay(rev, doc, msg)
            send_contributor_notification(based_on_revs, rev, doc, msg)

            # Schedule KB rebuild?
            statsd.incr('wiki.review')
            schedule_rebuild_kb()

            return HttpResponseRedirect(
                reverse('wiki.document_revisions', args=[document_slug]))

    if doc.parent:  # A translation
        # For diffing the based_on revision against, to help the user see if he
        # translated all the recent changes:
        parent_revision = doc.parent.localizable_or_latest_revision()
        template = 'wiki/review_translation.html'
    else:
        parent_revision = None
        template = 'wiki/review_revision.html'

    data = {
        'revision': rev,
        'document': doc,
        'form': form,
        'parent_revision': parent_revision,
        'revision_contributors': list(revision_contributors),
        'should_ask_significance': should_ask_significance
    }
    data.update(SHOWFOR_DATA)
    return jingo.render(request, template, data)