| 1 | == Extension Point : ''IWikiPageManipulator'' == |
| 2 | |
| 3 | ||'''Interface'''||''IWikiPageManipulator''||'''Since'''||0.10|| |
| 4 | ||'''Module'''||''trac.wiki''||'''Source'''||[source:trunk/trac/wiki/api.py#/IWikiPageManipulator api.py]|| |
| 5 | |
| 6 | The ''IWikiPageManipulator'' can manipulate and validate wiki pages before saving or before rendering. |
| 7 | |
| 8 | == Purpose == |
| 9 | |
| 10 | A plugin can add new restrictions on users when creating or changing wiki pages. They can also show validation warnings whenever a wiki page is rendered. (E.g. to help find validation errors in old content.) |
| 11 | |
| 12 | It's also possible to manipulate a page (although a [wiki:../trac.wiki.api.IWikiSyntaxProvider IWikiSyntaxProvider] may be more appropriate for that) or it's fields before saving. |
| 13 | |
| 14 | == Usage == |
| 15 | |
| 16 | Implementing the interface follows the standard guidelines found in [wiki:TracDev/ComponentArchitecture] and of course [wiki:TracDev/PluginDevelopment]. |
| 17 | |
| 18 | The `validate_wiki_page` method is called when a user creates or modifies a wiki page. Returning a list of messages rejects the (changed) page, returning `[]` accepts it. |
| 19 | |
| 20 | Note that the `validate_wiki_page` method can also be used to ''manipulate'' the page's fields before they are saved. |
| 21 | |
| 22 | Note that the previous values of a changed page can be accessed in `page.old_text`. (See comment:3:ticket:7731) |
| 23 | |
| 24 | The `prepare_wiki_page` method is called when a page is rendered. (Currently this is the only `prepare_*` method of a `I*Manipulator` interface that actually gets called.) |
| 25 | It can for example add validation warnings using `trac.web.chrome.add_warning`. |
| 26 | |
| 27 | == Examples == |
| 28 | |
| 29 | The following example implementation was taken from comment:3:ticket:9096. It validates wiki pages before saving and when rendering a page. |
| 30 | |
| 31 | {{{#!python |
| 32 | from trac.core import * |
| 33 | from trac.wiki.api import IWikiPageManipulator |
| 34 | from trac.web.chrome import add_warning |
| 35 | |
| 36 | class TracWikiValidator(Component): |
| 37 | |
| 38 | implements(IWikiPageManipulator) |
| 39 | |
| 40 | def validate(self, page): |
| 41 | lines = page.text.splitlines() |
| 42 | if not lines: |
| 43 | return ["Page shouldn't be empty"] |
| 44 | messages = [] |
| 45 | if not lines[0].lstrip().startswith("= "): |
| 46 | messages.append("First line must be the page's '= title ='") |
| 47 | # etc. |
| 48 | return messages |
| 49 | |
| 50 | # IWikiPageManipulator |
| 51 | |
| 52 | def prepare_wiki_page(self, req, page, fields): |
| 53 | for message in self.validate(page): |
| 54 | add_warning(req, message) |
| 55 | |
| 56 | def validate_wiki_page(self, req, page): |
| 57 | for message in self.validate(page): |
| 58 | yield ('text', message) |
| 59 | }}} |
| 60 | |
| 61 | == Available Implementations == |
| 62 | |
| 63 | * SpamFilter: Rejects spam. |
| 64 | * th:InputfieldTrapPlugin: Rejects spam with a hidden input field. |
| 65 | * th:MathCaptchaPlugin: Rejects spam with math question CAPTCHA. |
| 66 | * th:HierWikiPlugin: Rejects hierarchically unstructured wiki sub-pages. |
| 67 | * th:TagsPlugin: Uses a redirection trick to ''skip'' default validation. |
| 68 | * [http://code.optaros.com/trac/oforge/ OForge] (!WikiToolsPlugin): Uses a redirection trick to ''skip'' default validation. |
| 69 | * th:ForceCommentPlugin: Rejects changes where the ''comment'' field is not filled out. |
| 70 | |
| 71 | == Additional Information and References == |
| 72 | |
| 73 | * [http://www.edgewall.org/docs/trac-trunk/epydoc/trac.wiki.api.IWikiPageManipulator-class.html epydoc] |
| 74 | * [http://www.edgewall.org/docs/trac-trunk/html/api/trac_ticket_api.html#trac.wiki.api.IWikiPageManipulator API Reference] |
| 75 | * See [../trac.wiki.api.IWikiChangeListener trac.wiki.api.IWikiChangeListener] |
| 76 | * See [../trac.attachment.IAttachmentManipulator trac.attachment.IAttachmentManipulator], [../trac.ticket.api.ITicketManipulator trac.ticket.api.ITicketManipulator] |
| 77 | * Related tickets: |
| 78 | * [query:keywords=~IWikiPageManipulator IWikiPageManipulator keyword] |
| 79 | * [query:"status!=closed&component=wiki system" wiki system component] |
| 80 | * #10125 Discusses how `prepare_wiki_page` is the only `prepare_*` method of an `I*Manipulator` interface that actually gets called and how the others should be modelled after this. |
| 81 | |
| 82 | API Evolution: |
| 83 | * 0.10: Introduced |
| 84 | * [ticket:5992 0.11]: Collect all warnings instead of raising `InvalidWikiPage`. |
| 85 | * (Contains a SPAM test plugin) |
| 86 | * [wiki:TracDev/ApiChanges/0.12#IWikiPageManipulator 0.12]: Provide both `page.text` and `page.old_text`. (#7731) |
| 87 | * [ticket:9096 0.12] Introduced the call to `prepare_wiki_page` before rendering. |