mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-02-07 05:04:55 -05:00
wiki: Rework page creation.
This commit is contained in:
@@ -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')
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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}'" />
|
||||
|
||||
Reference in New Issue
Block a user