paul@0 | 1 | # -*- coding: iso-8859-1 -*- |
paul@0 | 2 | """ |
paul@0 | 3 | MoinMoin - MoinForms library |
paul@0 | 4 | |
paul@0 | 5 | @copyright: 2012 by Paul Boddie <paul@boddie.org.uk> |
paul@0 | 6 | @license: GNU GPL (v2 or later), see COPYING.txt for details. |
paul@0 | 7 | """ |
paul@0 | 8 | |
paul@0 | 9 | from MoinMoin import wikiutil |
paul@0 | 10 | from StringIO import StringIO |
paul@0 | 11 | from MoinSupport import * |
paul@0 | 12 | import re |
paul@0 | 13 | |
paul@0 | 14 | __version__ = "0.1" |
paul@0 | 15 | |
paul@0 | 16 | # Common formatting functions. |
paul@0 | 17 | |
paul@0 | 18 | def formatForm(text, request, fmt, attrs=None, write=None): |
paul@0 | 19 | |
paul@0 | 20 | """ |
paul@0 | 21 | Format the given 'text' using the specified 'request' and formatter 'fmt'. |
paul@0 | 22 | The optional 'attrs' can be used to control the presentation of the form. |
paul@0 | 23 | |
paul@0 | 24 | If the 'write' parameter is specified, use it to write output; otherwise, |
paul@0 | 25 | write output using the request. |
paul@0 | 26 | """ |
paul@0 | 27 | |
paul@0 | 28 | write = write or request.write |
paul@0 | 29 | page = request.page |
paul@0 | 30 | |
paul@0 | 31 | fields = getFields(get_form(request)) |
paul@0 | 32 | |
paul@0 | 33 | querystr = attrs and attrs.has_key("action") and ("action=%s" % attrs["action"]) or None |
paul@0 | 34 | |
paul@0 | 35 | write(fmt.rawHTML('<form method="post" action="%s">' % |
paul@0 | 36 | escattr(page.url(request, querystr)) |
paul@0 | 37 | )) |
paul@0 | 38 | |
paul@0 | 39 | output = getFormOutput(text, fields) |
paul@0 | 40 | write(formatText(output, request, fmt)) |
paul@0 | 41 | |
paul@0 | 42 | write(fmt.rawHTML('</form>')) |
paul@0 | 43 | |
paul@0 | 44 | def getFormOutput(text, fields): |
paul@0 | 45 | |
paul@0 | 46 | """ |
paul@0 | 47 | Combine regions found in the given 'text' and then return them as a single |
paul@0 | 48 | block. The reason for doing this, as opposed to just passing each region to |
paul@0 | 49 | a suitable parser for formatting, is that form sections may break up |
paul@0 | 50 | regions, and such sections may not define separate subregions but instead |
paul@0 | 51 | act as a means of conditional inclusion of text into an outer region. |
paul@0 | 52 | |
paul@0 | 53 | The given 'fields' are used to populate fields provided in forms and to |
paul@0 | 54 | control whether sections are populated or not. |
paul@0 | 55 | """ |
paul@0 | 56 | |
paul@0 | 57 | output = [] |
paul@0 | 58 | section = fields |
paul@0 | 59 | |
paul@0 | 60 | for region in getRegions(text, True): |
paul@0 | 61 | format, attributes, body, header, close = getFragmentFromRegion(region) |
paul@0 | 62 | |
paul@0 | 63 | # NOTE: Need to adjust FormField macros to use hierarchical names. |
paul@0 | 64 | |
paul@0 | 65 | # Include bare regions as they are. |
paul@0 | 66 | |
paul@0 | 67 | if format is None: |
paul@0 | 68 | output.append(region) |
paul@0 | 69 | |
paul@0 | 70 | # Include form sections only if fields exist for those sections. |
paul@0 | 71 | |
paul@0 | 72 | elif format == "form": |
paul@0 | 73 | section_name = attributes.get("section") |
paul@0 | 74 | if section_name and section.has_key(section_name): |
paul@0 | 75 | output.append(header) |
paul@0 | 76 | output.append(getFormOutput(body, section[section_name])) |
paul@0 | 77 | output.append(close) |
paul@0 | 78 | |
paul@0 | 79 | # Inspect and include other regions. |
paul@0 | 80 | |
paul@0 | 81 | else: |
paul@0 | 82 | output.append(header) |
paul@0 | 83 | output.append(getFormOutput(body, section)) |
paul@0 | 84 | output.append(close) |
paul@0 | 85 | |
paul@0 | 86 | return "".join(output) |
paul@0 | 87 | |
paul@0 | 88 | def getFields(d): |
paul@0 | 89 | |
paul@0 | 90 | """ |
paul@0 | 91 | Return the form fields hierarchy for the given dictionary 'd'. |
paul@0 | 92 | """ |
paul@0 | 93 | |
paul@0 | 94 | fields = {} |
paul@0 | 95 | |
paul@0 | 96 | for key, value in d.items(): |
paul@0 | 97 | |
paul@0 | 98 | # Reproduce the original hierarchy of the fields. |
paul@0 | 99 | |
paul@0 | 100 | section = fields |
paul@0 | 101 | parts = key.split("/") |
paul@0 | 102 | |
paul@0 | 103 | for part in parts[:-1]: |
paul@0 | 104 | try: |
paul@0 | 105 | name, index = part.split("$", 1) |
paul@0 | 106 | index = int(index) |
paul@0 | 107 | except ValueError: |
paul@0 | 108 | name, index = part, None |
paul@0 | 109 | |
paul@0 | 110 | if not section.has_key(name): |
paul@0 | 111 | section[name] = {} |
paul@0 | 112 | |
paul@0 | 113 | if not section[name].has_key(index): |
paul@0 | 114 | section[name][index] = {} |
paul@0 | 115 | |
paul@0 | 116 | section = section[name][index] |
paul@0 | 117 | |
paul@0 | 118 | section[parts[-1]] = value |
paul@0 | 119 | |
paul@0 | 120 | return fields |
paul@0 | 121 | |
paul@0 | 122 | def formatFormForOutputType(text, request, mimetype, attrs=None, write=None): |
paul@0 | 123 | |
paul@0 | 124 | """ |
paul@0 | 125 | Format the given 'text' using the specified 'request' for the given output |
paul@0 | 126 | 'mimetype'. |
paul@0 | 127 | |
paul@0 | 128 | The optional 'attrs' can be used to control the presentation of the form. |
paul@0 | 129 | |
paul@0 | 130 | If the 'write' parameter is specified, use it to write output; otherwise, |
paul@0 | 131 | write output using the request. |
paul@0 | 132 | """ |
paul@0 | 133 | |
paul@0 | 134 | write = write or request.write |
paul@0 | 135 | |
paul@0 | 136 | if mimetype == "text/html": |
paul@0 | 137 | write('<html>') |
paul@0 | 138 | write('<body>') |
paul@0 | 139 | fmt = request.html_formatter |
paul@0 | 140 | fmt.setPage(request.page) |
paul@0 | 141 | formatForm(text, request, fmt, attrs, write) |
paul@0 | 142 | write('</body>') |
paul@0 | 143 | write('</html>') |
paul@0 | 144 | |
paul@0 | 145 | # vim: tabstop=4 expandtab shiftwidth=4 |