wiki: Rework page creation.

This commit is contained in:
Andre D
2012-09-12 19:21:00 -05:00
committed by Neil Williams
parent f4bab12564
commit 4ecee12d33
5 changed files with 78 additions and 71 deletions

View File

@@ -196,7 +196,7 @@ def make_map():
mc('/help/gold', controller='redirect', action='redirect', dest='/gold/about')
mc('/help/*anything', controller='embed', action='help')
mc('/wiki/create/*page', controller='wiki', action='wiki_create')
mc('/wiki/notfound/*page', controller='wiki', action='wiki_notfound')
mc('/wiki/edit/*page', controller='wiki', action='wiki_revise')
mc('/wiki/revisions/*page', controller='wiki', action='wiki_revisions')
mc('/wiki/settings/*page', controller='wiki', action='wiki_settings')
@@ -204,6 +204,7 @@ def make_map():
mc('/wiki/revisions', controller='wiki', action='wiki_recent')
mc('/wiki/pages', controller='wiki', action='wiki_listing')
mc('/wiki/api/create', controller='wikiapi', action='wiki_create')
mc('/wiki/api/edit/*page', controller='wikiapi', action='wiki_edit')
mc('/wiki/api/hide/:revision/*page', controller='wikiapi', action='wiki_revision_hide')
mc('/wiki/api/revert/:revision/*page', controller='wikiapi', action='wiki_revision_revert')

View File

@@ -249,7 +249,7 @@ class VWikiPage(Validator):
class VWikiPageAndVersion(VWikiPage):
def run(self, page, *versions):
wp = VWikiPage.run(self, page)
if c.errors:
if self.has_errors:
return
validated = []
for v in versions:
@@ -260,14 +260,31 @@ class VWikiPageAndVersion(VWikiPage):
return tuple([wp] + validated)
class VWikiPageRevise(VWikiPage):
def __init__(self, *k, **kw):
VWikiPage.__init__(self, required=False, *k, **kw)
def may_not_create(self, page):
if c.is_wiki_mod and WikiPage.is_special(page):
return {'reason': 'PAGE_CREATED_ELSEWHERE'}
elif WikiPage.is_restricted(page):
self.set_error('RESTRICTED_PAGE', code=403)
return
elif page.count('/') > MAX_SEPARATORS:
return {'reason': 'PAGE_NAME_MAX_SEPARATORS', 'MAX_SEPARATORS': MAX_SEPARATORS}
elif len(page) > MAX_PAGE_NAME_LENGTH:
return {'reason': 'PAGE_NAME_LENGTH', 'max_length': MAX_PAGE_NAME_LENGTH}
def run(self, page, previous=None):
wp = VWikiPage.run(self, page)
if c.errors:
if self.has_errors:
return
if not wp:
return self.set_error('INVALID_PAGE', code=404)
if not this_may_revise(wp):
if not wp:
return self.set_error('PAGE_NOT_FOUND', code=404)
return self.set_error('MAY_NOT_REVISE', code=403)
if not wp:
c.error = self.may_not_create(page)
return (None, None)
if previous:
try:
prev = self.validversion(previous, wp._id)
@@ -275,25 +292,6 @@ class VWikiPageRevise(VWikiPage):
return
return (wp, prev)
return (wp, None)
class VWikiPageCreate(VWikiPage):
def __init__(self, param, **kw):
VWikiPage.__init__(self, param, required=False, **kw)
def run(self, page):
wp = VWikiPage.run(self, page)
if c.errors:
return
if wp:
c.error = {'reason': 'PAGE_EXISTS'}
elif c.is_wiki_mod and WikiPage.is_special(page):
c.error = {'reason': 'PAGE_CREATED_ELSEWHERE'}
elif WikiPage.is_restricted(page):
self.set_error('RESTRICTED_PAGE', code=403)
return
elif page.count('/') > MAX_SEPARATORS:
c.error = {'reason': 'PAGE_NAME_MAX_SEPARATORS', 'MAX_SEPARATORS': MAX_SEPARATORS}
elif len(page) > MAX_PAGE_NAME_LENGTH:
c.error = {'reason': 'PAGE_NAME_LENGTH', 'max_length': MAX_PAGE_NAME_LENGTH}
return this_may_revise()

View File

@@ -34,12 +34,11 @@ from r2.models.builder import WikiRevisionBuilder, WikiRecentRevisionBuilder
from r2.lib.template_helpers import join_urls
from r2.controllers.validator import VMarkdown
from r2.controllers.validator import VMarkdown, nop
from r2.controllers.validator.wiki import (VWikiPage, VWikiPageAndVersion,
VWikiModerator, VWikiPageRevise
VWikiPageCreate, this_may_view
wiki_validate)
VWikiModerator, VWikiPageRevise,
this_may_view, wiki_validate)
from r2.lib.pages.wiki import (WikiPageView, WikiNotFound, WikiRevisions,
WikiEdit, WikiSettings, WikiRecent,
@@ -59,7 +58,7 @@ from r2.lib.merge import ConflictException, make_htmldiff
from pylons.i18n import _
from r2.lib.pages import PaneStack
from r2.lib.utils import timesince
from r2.config import extensions
from r2.lib.base import abort
from r2.controllers.errors import WikiError
@@ -81,7 +80,7 @@ class WikiController(RedditController):
message = None
if not page:
return self.GET_wiki_create(page=c.page, view=True)
return self.redirect(join_urls(c.wiki_base_url, '/notfound/', c.page))
if version:
edit_by = version.author_name()
@@ -121,17 +120,17 @@ class WikiController(RedditController):
listing = WikiRevisionListing(builder).listing()
return WikiRevisions(listing).render()
@wiki_validate(may_create=VWikiPageCreate('page'))
def GET_wiki_create(self, may_create, page, view=False):
api = c.extension == 'json'
if c.error and c.error['reason'] == 'PAGE_EXISTS':
return self.redirect(join_urls(c.wiki_base_url, page))
elif not may_create or api:
if may_create and c.error:
@wiki_validate(wp=VWikiPageRevise('page'),
page=nop('page'))
def GET_wiki_notfound(self, wp, page):
api = c.render_style in extensions.API_TYPES
if wp[0]:
return self.redirect(join_urls(c.wiki_base_url, wp[0].name))
elif api:
if c.error:
self.handle_error(403, **c.error)
else:
self.handle_error(404, 'PAGE_NOT_FOUND', may_create=may_create)
self.handle_error(404, 'PAGE_NOT_CREATED')
elif c.error:
error = ''
if c.error['reason'] == 'PAGE_NAME_LENGTH':
@@ -141,20 +140,18 @@ class WikiController(RedditController):
elif c.error['reason'] == 'PAGE_NAME_MAX_SEPARATORS':
error = _('a max of %d separators "/" are allowed in a wiki page name.') % c.error['MAX_SEPARATORS']
return BoringPage(_("Wiki error"), infotext=error).render()
elif view:
return WikiNotFound().render()
elif may_create:
WikiPage.create(c.site, page)
url = join_urls(c.wiki_base_url, '/edit/', page)
return self.redirect(url)
else:
return WikiNotFound(page=page).render()
@wiki_validate(page=VWikiPageRevise('page', restricted=True))
def GET_wiki_revise(self, page, message=None, **kw):
page = page[0]
previous = kw.get('previous', page._get('revision'))
content = kw.get('content', page.content)
if not message and page.name in page_descriptions:
message = page_descriptions[page.name]
@wiki_validate(wp=VWikiPageRevise('page', restricted=True))
def GET_wiki_revise(self, wp, page, message=None, **kw):
wp = wp[0]
if not wp:
return self.redirect(join_urls(c.wiki_base_url, '/notfound/', page))
previous = kw.get('previous', wp._get('revision'))
content = kw.get('content', wp.content)
if not message and wp.name in page_descriptions:
message = page_descriptions[wp.name]
return WikiEdit(content, previous, alert=message).render()
@paginated_listing(max_page_size=100, backend='cassandra')
@@ -206,8 +203,8 @@ class WikiController(RedditController):
ModAction.create(c.site, c.user, 'wikipermlevel', description=description)
return self.GET_wiki_settings(page=page.name)
def handle_error(self, code, error=None, **data):
abort(WikiError(code, error, **data))
def handle_error(self, code, reason=None, **data):
abort(WikiError(code, reason, **data))
def pre(self):
RedditController.pre(self)
@@ -216,7 +213,9 @@ class WikiController(RedditController):
if not c.site._should_wiki:
self.handle_error(404, 'NOT_WIKIABLE') # /r/mod for an example
frontpage = isinstance(c.site, DefaultSR)
c.wiki_base_url = '/wiki' if frontpage else '/r/%s/wiki' % c.site.name
base = '' if frontpage else '/r/%s' % c.site.name
c.wiki_base_url = '%s/wiki' % base
c.wiki_api_url = '%s/wiki/api' % base
c.wiki_id = g.default_sr if frontpage else c.site.name
c.page = None
c.show_wiki_actions = True
@@ -233,9 +232,16 @@ class WikiController(RedditController):
class WikiApiController(WikiController):
@wiki_validate(pageandprevious=VWikiPageRevise(('page', 'previous'), restricted=True),
content=VMarkdown(('content')))
def POST_wiki_edit(self, pageandprevious, content):
content=VMarkdown(('content')),
page_name=nop('page'))
def POST_wiki_edit(self, pageandprevious, content, page_name):
page, previous = pageandprevious
if not page:
if c.error:
self.handle_error(403, **c.error)
page = WikiPage.create(c.site, page_name)
# Use the raw POST value as we need to tell the difference between
# None/Undefined and an empty string. The validators use a default
# value with both of those cases and would need to be changed.
@@ -249,10 +255,10 @@ class WikiApiController(WikiController):
if report.errors:
error_items = [x.message for x in sorted(report.errors)]
self.handle_error(415, 'SPECIAL_ERRORS', special_errors=error_items)
c.site.change_css(content, parsed, previous, reason=request.POST['reason'])
c.site.change_css(content, parsed, previous, reason=request.POST.get('reason', ''))
else:
try:
page.revise(content, previous, c.user.name, reason=request.POST['reason'])
page.revise(content, previous, c.user.name, reason=request.POST.get('reason', ''))
except ContentLengthError as e:
self.handle_error(403, 'CONTENT_LENGTH_ERROR', max_length = e.max_length)
@@ -287,7 +293,7 @@ class WikiApiController(WikiController):
def POST_wiki_revision_hide(self, pv, page, revision):
page, revision = pv
return json.dumps({'status': revision.toggle_hide()})
@wiki_validate(VWikiModerator(),
pv=VWikiPageAndVersion(('page', 'revision')))
def POST_wiki_revision_revert(self, pv, page, revision):

View File

@@ -24,10 +24,11 @@ class WikiPageListing(Templated):
Templated.__init__(self)
class WikiEditPage(Templated):
def __init__(self, page_content, previous):
def __init__(self, page_content='', previous='', show_reason_field=True):
self.page_content = page_content
self.previous = previous
self.base_url = c.wiki_base_url
self.show_reason_field = show_reason_field
Templated.__init__(self)
class WikiPageSettings(Templated):
@@ -94,13 +95,12 @@ class WikiPageView(WikiBase):
content = WikiView(content, context.get('edit_by'), context.get('edit_date'), diff=diff)
WikiBase.__init__(self, content, **context)
class WikiNotFound(WikiPageView):
def __init__(self, **context):
context['alert'] = _("page %s does not exist in this subreddit") % c.page
class WikiNotFound(WikiBase):
def __init__(self, page, **context):
context['alert'] = _("page %s does not exist in this subreddit") % page
context['actionless'] = True
create_link = '%s/create/%s' % (c.wiki_base_url, c.page)
text = _("a page with that name does not exist in this subreddit.\n\n[Create a page called %s](%s)") % (c.page, create_link)
WikiPageView.__init__(self, text, **context)
content = WikiEditPage(show_reason_field=False)
WikiBase.__init__(self, content, **context)
class WikiEdit(WikiBase):
def __init__(self, content, previous, **context):

View File

@@ -40,9 +40,11 @@
<form method="post" id="editform" data-page="${c.page}" onsubmit="r.wiki.submitEdit(event)">
<textarea name="content" rows="20" cols="20" style="width: 100%" id="content">${keep_space(thing.page_content)}</textarea>
<br/><br/>
<label for="reason">${_("reason for revision")}</label><br/>
<input type="text" name="reason" style="width: 100%" />
%if thing.show_reason_field:
<br/><br/>
<label for="reason">${_("reason for revision")}</label><br/>
<input type="text" name="reason" style="width: 100%" />
%endif
<input type="hidden" id="previous" name="previous" value="${thing.previous}" /><br/><br/>
<input type="submit" value="${_('save page')}" />
<input type="button" value="${_('cancel edit')}" onclick="location.href='${thing.base_url}/${c.page}'" />