LEFT | RIGHT |
1 # Copyright: 2012 MoinMoin:CheerXiao | 1 # Copyright: 2012 MoinMoin:CheerXiao |
2 # Copyright: 2003-2013 MoinMoin:ThomasWaldmann | 2 # Copyright: 2003-2013 MoinMoin:ThomasWaldmann |
3 # Copyright: 2011 MoinMoin:AkashSinha | 3 # Copyright: 2011 MoinMoin:AkashSinha |
4 # Copyright: 2011 MoinMoin:ReimarBauer | 4 # Copyright: 2011 MoinMoin:ReimarBauer |
5 # Copyright: 2008 MoinMoin:FlorianKrupicka | 5 # Copyright: 2008 MoinMoin:FlorianKrupicka |
6 # Copyright: 2010 MoinMoin:DiogenesAugusto | 6 # Copyright: 2010 MoinMoin:DiogenesAugusto |
7 # Copyright: 2001 Richard Jones <richard@bizarsoftware.com.au> | 7 # Copyright: 2001 Richard Jones <richard@bizarsoftware.com.au> |
8 # Copyright: 2001 Juergen Hermann <jh@web.de> | 8 # Copyright: 2001 Juergen Hermann <jh@web.de> |
9 # License: GNU GPL v2 (or any later version), see LICENSE.txt for details. | 9 # License: GNU GPL v2 (or any later version), see LICENSE.txt for details. |
10 | 10 |
(...skipping 29 matching lines...) Expand all Loading... |
40 | 40 |
41 from whoosh.query import Term, Prefix, And, Or, DateRange, Every | 41 from whoosh.query import Term, Prefix, And, Or, DateRange, Every |
42 | 42 |
43 from MoinMoin import log | 43 from MoinMoin import log |
44 logging = log.getLogger(__name__) | 44 logging = log.getLogger(__name__) |
45 | 45 |
46 from MoinMoin.i18n import _, L_, N_ | 46 from MoinMoin.i18n import _, L_, N_ |
47 from MoinMoin.themes import render_template, contenttype_to_class | 47 from MoinMoin.themes import render_template, contenttype_to_class |
48 from MoinMoin.apps.frontend import frontend | 48 from MoinMoin.apps.frontend import frontend |
49 from MoinMoin.forms import (OptionalText, RequiredText, URL, YourOpenID, YourEma
il, RequiredPassword, Checkbox, | 49 from MoinMoin.forms import (OptionalText, RequiredText, URL, YourOpenID, YourEma
il, RequiredPassword, Checkbox, |
50 InlineCheckbox, Select, Names, Tags, Natural, Hidden
, MultiSelect, Enum) | 50 InlineCheckbox, Select, Names, Tags, Natural, Hidden
, MultiSelect, Enum, validate_name, |
| 51 NameNotValidError) |
51 from MoinMoin.items import BaseChangeForm, Item, NonExistent, NameNotUniqueError
, FieldNotUniqueError | 52 from MoinMoin.items import BaseChangeForm, Item, NonExistent, NameNotUniqueError
, FieldNotUniqueError |
52 from MoinMoin.items.content import content_registry | 53 from MoinMoin.items.content import content_registry |
53 from MoinMoin import user, util | 54 from MoinMoin import user, util |
54 from MoinMoin.constants.keys import * | 55 from MoinMoin.constants.keys import * |
55 from MoinMoin.constants.itemtypes import ITEMTYPE_DEFAULT | 56 from MoinMoin.constants.itemtypes import ITEMTYPE_DEFAULT |
56 from MoinMoin.constants.chartypes import CHARS_UPPER, CHARS_LOWER | 57 from MoinMoin.constants.chartypes import CHARS_UPPER, CHARS_LOWER |
57 from MoinMoin.util import crypto | 58 from MoinMoin.util import crypto |
58 from MoinMoin.util.interwiki import url_for_item, split_fqname | 59 from MoinMoin.util.interwiki import url_for_item, split_fqname |
59 from MoinMoin.search import SearchForm | 60 from MoinMoin.search import SearchForm |
60 from MoinMoin.search.analyzers import item_name_analyzer | 61 from MoinMoin.search.analyzers import item_name_analyzer |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 Decorator factory to apply add_presenter(). | 352 Decorator factory to apply add_presenter(). |
352 """ | 353 """ |
353 return partial(add_presenter, view=view, add_trail=add_trail, abort404=abort
404) | 354 return partial(add_presenter, view=view, add_trail=add_trail, abort404=abort
404) |
354 | 355 |
355 | 356 |
356 # The first form accepts POST to allow modifying behavior like modify_item. | 357 # The first form accepts POST to allow modifying behavior like modify_item. |
357 # The second form only accpets GET since modifying a historical revision is not
allowed (yet). | 358 # The second form only accpets GET since modifying a historical revision is not
allowed (yet). |
358 @frontend.route('/<itemname:item_name>', defaults=dict(rev=CURRENT), methods=['G
ET', 'POST']) | 359 @frontend.route('/<itemname:item_name>', defaults=dict(rev=CURRENT), methods=['G
ET', 'POST']) |
359 @frontend.route('/+show/+<rev>/<itemname:item_name>', methods=['GET']) | 360 @frontend.route('/+show/+<rev>/<itemname:item_name>', methods=['GET']) |
360 def show_item(item_name, rev): | 361 def show_item(item_name, rev): |
361 flaskg.user.add_trail(item_name) | |
362 item_displayed.send(app._get_current_object(), | 362 item_displayed.send(app._get_current_object(), |
363 item_name=item_name) | 363 item_name=item_name) |
364 try: | 364 try: |
365 item = Item.create(item_name, rev_id=rev) | 365 item = Item.create(item_name, rev_id=rev) |
| 366 flaskg.user.add_trail(item_name) |
366 result = item.do_show(rev) | 367 result = item.do_show(rev) |
367 except AccessDenied: | 368 except AccessDenied: |
368 abort(403) | 369 abort(403) |
369 except FieldNotUniqueError: | 370 except FieldNotUniqueError: |
370 fqname = split_fqname(item_name) | 371 fqname = split_fqname(item_name) |
371 revs = flaskg.storage.documents(**fqname.query) | 372 revs = flaskg.storage.documents(**fqname.query) |
372 item_names = [] | 373 fq_names = [] |
373 for rev in revs: | 374 for rev in revs: |
374 item_names.extend(rev.fqnames) | 375 fq_names.extend(rev.fqnames) |
375 return render_template("link_list_no_item_panel.html", | 376 return render_template("link_list_no_item_panel.html", |
376 headline=_("Items with %(field)s %(value)s", fiel
d=fqname.field, value=fqname.value), | 377 headline=_("Items with %(field)s %(value)s", fiel
d=fqname.field, value=fqname.value), |
377 item_name=fqname.fullname, | 378 item_name=fqname.fullname, |
378 item_names=item_names) | 379 fq_names=fq_names) |
379 return result | 380 return result |
380 | 381 |
381 | 382 |
382 @frontend.route('/<itemname:item_name>/') # note: unwanted trailing slash | 383 @frontend.route('/<itemname:item_name>/') # note: unwanted trailing slash |
383 @frontend.route('/+show/<itemname:item_name>') | 384 @frontend.route('/+show/<itemname:item_name>') |
384 def redirect_show_item(item_name): | 385 def redirect_show_item(item_name): |
385 return redirect(url_for_item(item_name)) | 386 return redirect(url_for_item(item_name)) |
386 | 387 |
387 | 388 |
388 @presenter('dom', abort404=False) | 389 @presenter('dom', abort404=False) |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 abort(403) | 517 abort(403) |
517 if not flaskg.user.may.write(item_name): | 518 if not flaskg.user.may.write(item_name): |
518 abort(403) | 519 abort(403) |
519 return item.do_modify() | 520 return item.do_modify() |
520 | 521 |
521 | 522 |
522 class TargetChangeForm(BaseChangeForm): | 523 class TargetChangeForm(BaseChangeForm): |
523 target = RequiredText.using(label=L_('Target')).with_properties(placeholder=
L_("The name of the target item")) | 524 target = RequiredText.using(label=L_('Target')).with_properties(placeholder=
L_("The name of the target item")) |
524 | 525 |
525 | 526 |
| 527 class ValidRevert(Validator): |
| 528 """ |
| 529 Validator for a valid revert form. |
| 530 """ |
| 531 invalid_name_msg = '' |
| 532 |
| 533 def validate(self, element, state): |
| 534 """ |
| 535 Check whether the names present in the previous meta are not taken by so
me other item. |
| 536 """ |
| 537 try: |
| 538 validate_name(state['meta'], state[FQNAME], state['meta'].get(ITEMID
)) |
| 539 return True |
| 540 except NameNotValidError as e: |
| 541 self.invalid_name_msg = _(e) |
| 542 return self.note_error(element, state, 'invalid_name_msg') |
| 543 |
| 544 |
526 class RevertItemForm(BaseChangeForm): | 545 class RevertItemForm(BaseChangeForm): |
527 name = 'revert_item' | 546 name = 'revert_item' |
| 547 validators = [ValidRevert()] |
528 | 548 |
529 | 549 |
530 class DeleteItemForm(BaseChangeForm): | 550 class DeleteItemForm(BaseChangeForm): |
531 name = 'delete_item' | 551 name = 'delete_item' |
532 | 552 |
533 | 553 |
534 class DestroyItemForm(BaseChangeForm): | 554 class DestroyItemForm(BaseChangeForm): |
535 name = 'destroy_item' | 555 name = 'destroy_item' |
536 | 556 |
537 | 557 |
(...skipping 10 matching lines...) Expand all Loading... |
548 if not flaskg.user.may.write(item_name): | 568 if not flaskg.user.may.write(item_name): |
549 abort(403) | 569 abort(403) |
550 if isinstance(item, NonExistent): | 570 if isinstance(item, NonExistent): |
551 abort(404, item_name) | 571 abort(404, item_name) |
552 if request.method in ['GET', 'HEAD']: | 572 if request.method in ['GET', 'HEAD']: |
553 form = RevertItemForm.from_defaults() | 573 form = RevertItemForm.from_defaults() |
554 TextCha(form).amend_form() | 574 TextCha(form).amend_form() |
555 elif request.method == 'POST': | 575 elif request.method == 'POST': |
556 form = RevertItemForm.from_flat(request.form) | 576 form = RevertItemForm.from_flat(request.form) |
557 TextCha(form).amend_form() | 577 TextCha(form).amend_form() |
558 if form.validate(): | 578 state = dict(fqname=item.fqname, meta=dict(item.meta)) |
| 579 if form.validate(state): |
559 item.revert(form['comment']) | 580 item.revert(form['comment']) |
560 return redirect(url_for_item(item_name)) | 581 return redirect(url_for_item(item_name)) |
561 return render_template(item.revert_template, | 582 return render_template(item.revert_template, |
562 item=item, item_name=item_name, | 583 item=item, fqname=item.fqname, |
563 rev_id=rev, | 584 rev_id=rev, |
564 form=form, | 585 form=form, |
565 ) | 586 ) |
566 | 587 |
567 | 588 |
568 @frontend.route('/+rename/<itemname:item_name>', methods=['GET', 'POST']) | 589 @frontend.route('/+rename/<itemname:item_name>', methods=['GET', 'POST']) |
569 def rename_item(item_name): | 590 def rename_item(item_name): |
570 try: | 591 try: |
571 item = Item.create(item_name) | 592 item = Item.create(item_name) |
572 except AccessDenied: | 593 except AccessDenied: |
(...skipping 1403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1976 response.cache_control.public = is_public | 1997 response.cache_control.public = is_public |
1977 response.cache_control.max_age = cache_timeout | 1998 response.cache_control.max_age = cache_timeout |
1978 response.expires = int(time.time() + cache_timeout) | 1999 response.expires = int(time.time() + cache_timeout) |
1979 return response | 2000 return response |
1980 | 2001 |
1981 | 2002 |
1982 @frontend.errorhandler(404) | 2003 @frontend.errorhandler(404) |
1983 def page_not_found(e): | 2004 def page_not_found(e): |
1984 return render_template('404.html', | 2005 return render_template('404.html', |
1985 item_name=e.description), 404 | 2006 item_name=e.description), 404 |
LEFT | RIGHT |