Beispiel #1
0
    def expand_macro(self, formatter, name, text):

        req = formatter.req
        context = formatter.context
        resource = context.resource

        # Process the arguments.
        args, kwargs = parse_args(text)

        if 'ticket' not in kwargs and len(args)>0:
            kwargs['ticket'] = args[0]
        elif 'ticket' not in kwargs and not len(args):
            kwargs['ticket'] = str( WikiPage(self.env, resource).name )   # This seems to provide the correct ticket id.

        try:
            kwargs['ticket'] = int( kwargs.get('ticket').lstrip('#') )
        except ValueError:
            raise TracError('No ticket id supplied or it is not valid integer value.')

        ticket = Ticket( self.env, kwargs['ticket'] )

        self.childtickets = {}    # { parent -> children } - 1:n

        db = self.env.get_db_cnx() 
        cursor = db.cursor() 
        cursor.execute("SELECT ticket,value FROM ticket_custom WHERE name='parent'")
        for child,parent in cursor.fetchall():
            if parent and re.match('#\d+',parent):
                self.childtickets.setdefault( int(parent.lstrip('#')), [] ).append(child)

        # First ticket has no indentation.
        ticket['indent'] = '0'

        # List of tickets that will be displayed.
        if as_bool( kwargs.get('root') ):
            self.tickets = [ ticket, ]
        else:
            self.tickets = []

        # Do this neater!
        self.indent_children(ticket)

        def ticket_anchor(t):
            return tag.a( '#%s' % t.id, class_=t['status'], href=req.href.ticket(int(t.id)), title="%s : %s : %s" % (t['type'],t['owner'],t['status']))

        def_list = tag.dl(
                [( tag.dt(ticket_anchor(t),style='padding-left: %spx;' % (t['indent']*20)), tag.dd("%s" % t['summary'])) for t in self.tickets],
                class_='wiki compact',
                )

        if as_bool( kwargs.get('border') ):
            return tag.fieldset(
                    def_list,
                    tag.legend('Ticket Child Tree (#%s)' % ticket.id),
                    class_='description',
                    )
        else:
            return tag.div(def_list)
Beispiel #2
0
    def _field_group(self, req, group):
        fieldset_id = 'properties_%s' % group['name']
        table_id = 'table_%s' % group['name']

        fieldset = tag.fieldset(id=fieldset_id, class_='property_group')
        fieldset.append(tag.legend(group['label']))
        fieldset.append(tag.table(id=table_id))

        return fieldset
Beispiel #3
0
    def _field_group(self, req, group):
        fieldset_id = 'properties_%s' % group['name']
        table_id = 'table_%s' % group['name']

        fieldset = tag.fieldset(id=fieldset_id, class_='property_group')
        fieldset.append(tag.legend(group['label']))
        fieldset.append(tag.table(id=table_id))

        return fieldset
Beispiel #4
0
 def _generate_attachmentflags_fieldset(self,
                                        readonly=True,
                                        current_flags=None,
                                        form=False):
     fields = Fragment()
     for flag in self.known_flags:
         flagid = 'flag_' + flag
         if current_flags and flag in current_flags:
             date = datetime.datetime.fromtimestamp(
                 current_flags[flag]["updated_on"], utc)
             text = tag.span(
                 tag.strong(flag), " set by ",
                 tag.em(current_flags[flag]["updated_by"]), ", ",
                 tag.span(pretty_timedelta(date),
                          title=format_datetime(date)), " ago")
             if readonly == True:
                 fields += tag.input(text, \
                                     type='checkbox', id=flagid, \
                                     name=flagid, checked="checked",
                                     disabled="true") + tag.br()
             else:
                 fields += tag.input(text, \
                                     type='checkbox', id=flagid, \
                                     name=flagid, checked="checked") + tag.br()
         else:
             if readonly == True:
                 fields += tag.input(flag, \
                                     type='checkbox', id=flagid, \
                                     name=flagid, disabled="true") + tag.br()
             else:
                 fields += tag.input(flag, \
                                     type='checkbox', id=flagid, \
                                     name=flagid) + tag.br()
     if form and not readonly:
         return tag.form(tag.fieldset(
             tag.legend("Attachment Flags") + fields,
             tag.input(type="hidden", name="action", value="update_flags"),
             tag.input(type="submit", value="Update flags")),
                         method="POST")
     return tag.fieldset(tag.legend("Attachment Flags") + fields)
Beispiel #5
0
    def filter_stream(self, req, method, filename, stream, data):
        if req.path_info.startswith('/register') and (
                req.method == 'GET' or 'registration_error' in data):
            question = None
            if self.question is not None and len(self.question) > 0:
                question = tag.label(
                    tag(self.question + " "),
                    tag.input(id='question', type='text', name='question'))
            # First Fieldset of the registration form XPath match
            xpath_match = '//form[@id="acctmgr_registerform"]/fieldset[1]'
            if question is None:
                return stream
            else:
                return stream | Transformer(xpath_match). \
                    append(tag(Markup(question)))
        # Admin Configuration
        elif req.path_info.startswith('/admin/accounts/config'):
            api_html = tag.div(
                tag.label("Question:", for_="registerquestion_question") +
                tag.input(class_="textwidget",
                          name="question",
                          value=self.question,
                          size=60)
            ) + tag.div(
                tag.label("Answer:", for_="registerquestion_answer") +
                tag.input(class_="textwidget",
                          name="answer",
                          value=self.answer,
                          size=60)
            ) + tag.div(
                tag.label("Hint:", for_="registerquestion_hint") + tag.input(
                    class_="textwidget", name="hint", value=self.hint, size=60)
            ) + tag.br()

            # First fieldset of the Account Manager config form
            xpath_match = '//form[@id="accountsconfig"]/fieldset[1]'

            return stream | Transformer(xpath_match). \
                before(tag.fieldset(tag.legend("Anti-Robot Question For Registration") + api_html))
        return stream
Beispiel #6
0
    def filter_stream(self, req, method, filename, stream, data):
        if req.path_info.startswith('/register') and (
            req.method == 'GET' or
            'registration_error' in data):
            question = None
            if self.question is not None and len(self.question)>0:
                question = tag.label(
                    tag(self.question + " "),
                    tag.input(id='question', type='text', name='question')
                    )
            # First Fieldset of the registration form XPath match
            xpath_match = '//form[@id="acctmgr_registerform"]/fieldset[1]'
            if question is None:
                return stream
            else:
                return stream | Transformer(xpath_match). \
                    append(tag(Markup(question)))
        # Admin Configuration
        elif req.path_info.startswith('/admin/accounts/config'):
            api_html = tag.div(
                tag.label("Question:", for_="registerquestion_question") +
                tag.input(class_="textwidget", name="question",
                          value=self.question, size=60)
            ) + tag.div(
                tag.label("Answer:", for_="registerquestion_answer") +
                tag.input(class_="textwidget", name="answer",
                          value=self.answer, size=60)
            ) + tag.div(
                tag.label("Hint:", for_="registerquestion_hint") +
                tag.input(class_="textwidget", name="hint",
                          value=self.hint, size=60)
            ) + tag.br()


            # First fieldset of the Account Manager config form
            xpath_match = '//form[@id="accountsconfig"]/fieldset[1]'

            return stream | Transformer(xpath_match). \
                before(tag.fieldset(tag.legend("Anti-Robot Question For Registration") + api_html))
        return stream
    def filter_stream(self, req, method, filename, stream, data):
        if req.path_info.startswith('/register') and (
            req.method == 'GET' or
            'registration_error' in data or
            'captcha_error' in req.session):
            if not (self.private_key or self.private_key):
                return stream
            captcha_opts = tag.script("""\
var RecaptchaOptions = {
  theme: "%s",
  lang: "%s"
}""" % (self.theme, self.lang), type='text/javascript')
            captcha_js = captcha.displayhtml(
                self.public_key, use_ssl=True,
                error='reCAPTCHA incorrect. Please try again.'
            )
            # First Fieldset of the registration form XPath match
            xpath_match = '//form[@id="acctmgr_registerform"]/fieldset[1]'
            return stream | Transformer(xpath_match). \
                append(captcha_opts + tag(Markup(captcha_js)))
        # Admin Configuration
        elif req.path_info.startswith('/admin/accounts/config'):
            api_html = tag.div(
                tag.label("Public Key:", for_="recaptcha_public_key") +
                tag.input(class_="textwidget", name="recaptcha_public_key",
                          value=self.public_key, size=40)
            ) + tag.div(
                tag.label("Private Key:", for_="recaptcha_private_key") +
                tag.input(class_="textwidget", name="recaptcha_private_key",
                          value=self.private_key, size=40)
            )
            if not (self.private_key or self.public_key):
                api_html = tag.div(
                    tag.a("Generate a reCAPTCHA API key for this Trac "
                          "instance domain.", target="_blank",
                          href="https://recaptcha.net/api/getkey?domain=%s&"
                            "app=TracRecaptchaRegister" %
                            req.environ.get('SERVER_NAME')
                    )
                ) + tag.br() + api_html

            theme_html = tag.div(
                tag.label("reCPATCHA theme:", for_='recaptcha_theme') +
                tag.select(
                    tag.option("Black Glass",
                               value="blackglass",
                               selected=self.theme=='blackglass' or None) +
                    tag.option("Clean",
                               value="clean",
                               selected=self.theme=='clean' or None) +
                    tag.option("Red",
                               value="red",
                               selected=self.theme=='red' or None) +
                    tag.option("White",
                               value="white",
                               selected=self.theme=='white' or None),
                    name='recaptcha_theme'
                )
            )

            language_html = tag.div(
                tag.label("reCAPTCHA language:", for_='recaptcha_lang') +
                tag.select(
                    tag.option("Dutch",
                               value="nl",
                               selected=self.lang=='nl' or None) +
                    tag.option("English",
                               value="en",
                               selected=self.lang=='en' or None) +
                    tag.option("French",
                               selected=self.lang=='fr' or None) +
                    tag.option("German",
                               value="de",
                               selected=self.lang=='de' or None) +
                    tag.option("Portuguese",
                               value="pt",
                               selected=self.lang=='pt' or None) +
                    tag.option("Russian",
                               value="ru",
                               selected=self.lang=='ru' or None) +
                    tag.option("Spanish",
                               value="es",
                               selected=self.lang=='es' or None) +
                    tag.option("Turkish",
                               value="tr",
                               selected=self.lang=='tr' or None),
                    name='recaptcha_lang'))

            # First fieldset of the Account Manager config form
            xpath_match = '//form[@id="accountsconfig"]/fieldset[1]'

            return stream | Transformer(xpath_match). \
                before(tag.fieldset(tag.legend("reCAPTCHA") + api_html +
                                    tag.br() + theme_html + language_html))
        return stream
    def filter_stream(self, req, method, filename, stream, data):
        if req.path_info.startswith('/register') and (
                req.method == 'GET' or 'registration_error' in data
                or 'captcha_error' in req.session):
            if not (self.private_key or self.private_key):
                return stream
            captcha_opts = tag.script("""\
var RecaptchaOptions = {
  theme: "%s",
  lang: "%s"
}""" % (self.theme, self.lang),
                                      type='text/javascript')
            captcha_js = captcha.displayhtml(
                self.public_key,
                use_ssl=req.scheme == 'https',
                error='reCAPTCHA incorrect. Please try again.')
            # First Fieldset of the registration form XPath match
            xpath_match = '//form[@id="acctmgr_registerform"]/fieldset[1]'
            return stream | Transformer(xpath_match). \
                append(captcha_opts + tag(Markup(captcha_js)))
        # Admin Configuration
        elif req.path_info.startswith('/admin/accounts/config'):
            api_html = tag.div(
                tag.label("Public Key:", for_="recaptcha_public_key") +
                tag.input(class_="textwidget",
                          name="recaptcha_public_key",
                          value=self.public_key,
                          size=40)
            ) + tag.div(
                tag.label("Private Key:", for_="recaptcha_private_key") +
                tag.input(class_="textwidget",
                          name="recaptcha_private_key",
                          value=self.private_key,
                          size=40))
            if not (self.private_key or self.public_key):
                api_html = tag.div(
                    tag.a(
                        "Generate a reCAPTCHA API key for this Trac "
                        "instance domain.",
                        target="_blank",
                        href="http://recaptcha.net/api/getkey?domain=%s&"
                        "app=TracRecaptchaRegister" %
                        req.environ.get('SERVER_NAME'))) + tag.br() + api_html

            theme_html = tag.div(
                tag.label("reCPATCHA theme:", for_='recaptcha_theme') +
                tag.select(
                    tag.option("Black Glass",
                               value="blackglass",
                               selected=self.theme == 'blackglass' or None) +
                    tag.option("Clean",
                               value="clean",
                               selected=self.theme == 'clean' or None) +
                    tag.option("Red",
                               value="red",
                               selected=self.theme == 'red' or None) +
                    tag.option("White",
                               value="white",
                               selected=self.theme == 'white' or None),
                    name='recaptcha_theme'))

            language_html = tag.div(
                tag.label("reCAPTCHA language:", for_='recaptcha_lang') +
                tag.select(tag.option(
                    "Dutch", value="nl", selected=self.lang == 'nl' or None
                ) + tag.option(
                    "English", value="en", selected=self.lang == 'en' or None
                ) + tag.option("French", selected=self.lang == 'fr' or None) +
                           tag.option("German",
                                      value="de",
                                      selected=self.lang == 'de' or None) +
                           tag.option("Portuguese",
                                      value="pt",
                                      selected=self.lang == 'pt' or None) +
                           tag.option("Russian",
                                      value="ru",
                                      selected=self.lang == 'ru' or None) +
                           tag.option("Spanish",
                                      value="es",
                                      selected=self.lang == 'es' or None) +
                           tag.option("Turkish",
                                      value="tr",
                                      selected=self.lang == 'tr' or None),
                           name='recaptcha_lang'))

            # First fieldset of the Account Manager config form
            xpath_match = '//form[@id="accountsconfig"]/fieldset[1]'

            return stream | Transformer(xpath_match). \
                before(tag.fieldset(tag.legend("reCAPTCHA") + api_html +
                                    tag.br() + theme_html + language_html))
        return stream
Beispiel #9
0
    def expand_macro(self, formatter, name, args):
        req = formatter.req
        tag_system = TagSystem(self.env)

        all_releases = natural_sort([r.id for r, _ in
                                     tag_system.query(req, 'realm:wiki release')])
        all_categories = sorted([r.id for r, _ in
                                 tag_system.query(req, 'realm:wiki type')])

        hide_release_picker = False
        hide_fieldset_legend = False
        hide_fieldset_description = False
        other = []
        if args:
            categories = []
            releases = []
            for arg in args.split():
                if arg in all_releases:
                    hide_release_picker = True
                    releases.append(arg)
                elif arg in all_categories:
                    categories.append(arg)
                else:
                    other.append(arg)

            if len(categories) or len(releases):
                hide_fieldset_description = True

            if not len(categories):
                categories = all_categories
            elif len(categories) == 1:
                hide_fieldset_legend = True

            if not len(releases):
                releases = all_releases
        else:
            categories = all_categories
            releases = all_releases

        if 'update_th_filter' in req.args:
            show_releases = req.args.get('release', ['0.11'])
            if isinstance(show_releases, basestring):
                show_releases = [show_releases]
            req.session['th_release_filter'] = ','.join(show_releases)
        else:
            show_releases = req.session.get('th_release_filter', '0.11').split(',')

        output = ""
        if not hide_release_picker:
            style = "text-align:right; padding-top:1em; margin-right:5em;"
            form = builder.form('\n', style=style, method="get")

            style = "font-size:xx-small;"
            span = builder.span("Show hacks for releases:", style=style)

            for version in releases:
                inp = builder.input(version, type_="checkbox", name="release",
                                    value=version)
                if version in show_releases:
                    inp(checked="checked")
                span(inp, '\n')

            style = "font-size:xx-small; padding:0; border:solid 1px black;"
            span(builder.input(name="update_th_filter", type_="submit",
                               style=style, value="Update"), '\n')
            form('\n', span, '\n')
            output = "%s%s\n" % (output, form)


        def link(resource):
            return render_resource_link(self.env, formatter.context,
                                        resource, 'compact')

        for category in categories:
            page = WikiPage(self.env, category)
            match = self.title_extract.search(page.text)
            if match:
                cat_title = '%s' % match.group(1).strip()
                cat_body = self.title_extract.sub('', page.text, 1)
            else:
                cat_title = '%s' % category
                cat_body = page.text
            cat_body = self.self_extract.sub('', cat_body).strip()

            style = "padding:1em; margin:0em 5em 2em 5em; border:1px solid #999;"
            fieldset = builder.fieldset('\n', style=style)
            if not hide_fieldset_legend:
                legend = builder.legend(style="color: #999;")
                legend(builder.a(cat_title, href=self.env.href.wiki(category)))
                fieldset(legend, '\n')
            if not hide_fieldset_description:
                fieldset(builder.p(wiki_to_html(cat_body, self.env, req)))

            ul = builder.ul('\n', class_="listtagged")
            query = 'realm:wiki (%s) %s %s' % \
                (' or '.join(show_releases), category, ' '.join(other))

            lines = 0
            for resource, tags in tag_system.query(req, query):
                # filter out the page used to make important tags
                # persistent
                if resource.id == "tags/persistent":
                    continue

                lines += 1
                li = builder.li(link(resource), ': ')

                page = WikiPage(self.env, resource)
                match = self.title_extract.search(page.text)
                description = "''no description available''"
                if match:
                    if match.group(1):
                        description = match.group(1).strip()

                li(wiki_to_oneliner(description, self.env, req=req))
                if tags:
                    if hide_fieldset_legend == False and category in tags:
                        tags.remove(category)
                        self.log.debug("hide %s: no legend" % category)
                    for o in other:
                        if o in tags: tags.remove(o)
                    rendered_tags = [ link(resource('tag', tag))
                                      for tag in natural_sort(tags) ]

                    span = builder.span(style="font-size:xx-small;")
                    span(' (tags: ', rendered_tags[0],
                       [(', ', tag) for tag in rendered_tags[1:]], ')')
                    li(span)
                ul(li, '\n')

            if lines:
                fieldset(ul, '\n')
            else:
                message = "No results for %s." % \
                    (hide_release_picker and "this version" or "your selection")
                fieldset(builder.p(builder.em(message)), '\n')
            output = "%s%s\n" % (output, fieldset)

        return output
Beispiel #10
0
def AddComment(macro, environ, data, *args, **kwargs):
    """Display an add comment form allowing users to post comments.

    This macro allows you to display an add comment form on the current
    page allowing users to post comments. The comments are added to the
    page's content itself.
    
    **Arguments:** //No Arguments//

    **Example(s):**
    {{{
    <<AddComment>>
    }}}

    <<AddComment>>
    """

    # Setup info and defaults
    parser = environ.parser
    request = environ.request

    page = data["page"]
    page_name = page["name"]
    page_text = page["text"]

    # Get the data from the POST
    comment = request.kwargs.get("comment", "")
    action = request.kwargs.get("action", "")
    author = request.kwargs.get("author", environ._user())

    # Ensure <<AddComment>> is not present in comment, so that infinite
    # recursion does not occur.
    comment = re.sub("(^|[^!])(\<\<AddComment)", "\\1!\\2", comment)

    the_preview = None
    the_comment = None

    # If we are submitting or previewing, inject comment as it should look
    if action == "preview":
        the_preview = tag.div(tag.h1("Preview"), id="preview")
        the_preview += tag.div(parser.generate(comment,
                                               environ=(environ, data)),
                               class_="article")

    # When submitting, inject comment before macro
    if comment and action == "save":
        new_text = ""
        comment_text = "\n==== Comment by %s on %s ====\n\n%s\n\n" % (
            author, time.strftime('%c', time.localtime()), comment)
        for line in page_text.split("\n"):
            if line.find("<<AddComment") == 0:
                new_text += comment_text
            new_text += line + "\n"

        search = environ.search
        storage = environ.storage

        storage.reopen()
        search.update(environ)

        storage.save_text(page_name, new_text, author,
                          "Comment added by %s" % author)

        search.update_page(environ.get_page(page_name),
                           page_name,
                           text=new_text)

        the_comment = tag.div(parser.generate(comment_text,
                                              environ=(environ, data)),
                              class_="article")

    the_form = tag.form(
        tag.input(type="hidden", name="parent", value=page["node"]),
        tag.fieldset(
            tag.legend("Add Comment"),
            tag.p(tag.textarea(
                (not action in ("cancel", "save") and comment or ""),
                id="comment",
                name="comment",
                cols=80,
                rows=5),
                  class_="text"),
            tag.h4(tag.label("Your email or username:"******"author")),
            tag.p(tag.input(id="author",
                            name="author",
                            type="text",
                            value=(not action in ("cancel", "save")) and author
                            or ""),
                  class_="input"),
            tag.p(tag.button("Preview",
                             type="submit",
                             name="action",
                             value="preview"),
                  tag.button("Save",
                             type="submit",
                             name="action",
                             value="save"),
                  tag.button("Cancel",
                             type="submit",
                             name="action",
                             value="cancel"),
                  class_="button"),
        ),
        method="post",
        action="")

    return tag(the_preview, the_comment, the_form)
Beispiel #11
0
class AddCommentMacro(WikiMacroBase):
    """A macro to add comments to a page. Usage:
    {{{
    [[AddComment]]
    }}}
    The macro accepts one optional argument that allows appending
    to the wiki page even though user may not have modify permission:
    {{{
    [[AddComment(appendonly)]]
    }}}
    """
    implements(IWikiMacroProvider, IRequestFilter, IMacroPoster)

    def expand_macro(self, formatter, name, content):

        args, kw = parse_args(content)
        req = formatter.req
        context = formatter.context

        # Prevent multiple inclusions - store a temp in req
        if hasattr(req, 'addcommentmacro'):
            raise TracError('\'AddComment\' macro cannot be included twice.')
        req.addcommentmacro = True

        # Prevent it being used outside of wiki page context
        resource = context.resource
        if not resource.realm == 'wiki':
            raise TracError(
                '\'AddComment\' macro can only be used in Wiki pages.')

        # Setup info and defaults
        authname = req.authname
        page = WikiPage(self.env, resource)
        page_url = req.href.wiki(resource.id)
        wikipreview = req.args.get("preview", "")

        # Can this user add a comment to this page?
        appendonly = ('appendonly' in args)
        cancomment = False
        if page.readonly:
            if 'WIKI_ADMIN' in req.perm(resource):
                cancomment = True
        elif 'WIKI_MODIFY' in req.perm(resource):
            cancomment = True
        elif appendonly and 'WIKI_VIEW' in req.perm(resource):
            cancomment = True
        else:
            self.log.debug(
                'Insufficient privileges for %s to AddComment to %s',
                req.authname, resource.id)

        # Get the data from the POST
        comment = req.args.get("addcomment", "")
        preview = req.args.get("previewaddcomment", "")
        cancel = req.args.get("canceladdcomment", "")
        submit = req.args.get("submitaddcomment", "")
        if not cancel and req.authname == 'anonymous':
            authname = req.args.get("authoraddcomment", authname)

        # Ensure [[AddComment]] is not present in comment, so that infinite
        # recursion does not occur.
        comment = to_unicode(
            re.sub('(^|[^!])(\[\[AddComment)', '\\1!\\2', comment))

        the_preview = the_message = the_form = tag()

        # If we are submitting or previewing, inject comment as it should look
        if cancomment and comment and (preview or submit):
            heading = tag.h4("Comment by ",
                             authname,
                             " on ",
                             to_unicode(time.strftime('%c', time.localtime())),
                             id="commentpreview")
            if preview:
                the_preview = tag.div(heading,
                                      format_to_html(self.env, context,
                                                     comment),
                                      class_="wikipage",
                                      id="preview")

        # Check the form_token
        form_ok = True
        if submit and req.args.get('__FORM_TOKEN', '') != req.form_token:
            form_ok = False
            the_message = tag.div(tag.strong("ERROR: "),
                                  "AddComment received incorrect form token. "
                                  "Do you have cookies enabled?",
                                  class_="system-message")

        # When submitting, inject comment before macro
        if comment and submit and cancomment and form_ok:
            submitted = False
            newtext = ""
            for line in page.text.splitlines():
                if line.find('[[AddComment') == 0:
                    newtext += "==== Comment by %s on %s ====\n%s\n\n" % (
                        authname,
                        to_unicode(time.strftime('%c',
                                                 time.localtime())), comment)
                    submitted = True
                newtext += line + "\n"
            if submitted:
                page.text = newtext

                # Let the wiki page manipulators have a look at the
                # submission.
                valid = True
                req.args.setdefault('comment', 'Comment added.')
                try:
                    for manipulator in WikiModule(self.env).page_manipulators:
                        for field, message in manipulator.validate_wiki_page(
                                req, page):
                            valid = False
                            if field:
                                the_message += tag.div(tag.strong(
                                    "invalid field '%s': " % field),
                                                       message,
                                                       class_="system-message")
                            else:
                                the_message += tag.div(tag.strong("invalid: "),
                                                       message,
                                                       class_="system-message")

                # The TracSpamfilterPlugin does not generate messages,
                # but throws RejectContent.
                except TracError, s:
                    valid = False
                    the_message += tag.div(tag.strong("ERROR: "),
                                           s,
                                           class_="system-message")

                if valid:
                    page.save(authname, req.args['comment'],
                              req.environ['REMOTE_ADDR'])
                    # We can't redirect from macro as it will raise RequestDone
                    # which like other macro errors gets swallowed in the Formatter.
                    # We need to re-raise it in a post_process_request instead.
                    try:
                        self.env.log.debug(
                            "AddComment saved - redirecting to: %s" % page_url)
                        req._outheaders = []
                        req.redirect(page_url)
                    except RequestDone:
                        req.addcomment_raise = True
            else:
                the_message = tag.div(
                    tag.strong("ERROR: "), "[[AddComment]] "
                    "macro call must be the only content on its line. "
                    "Could not add comment.",
                    class_="system-message")

        the_form = tag.form(
            tag.fieldset(
                tag.legend("Add comment"),
                tag.div((wikipreview and "Page preview..." or None),
                        tag.textarea((not cancel and comment or ""),
                                     class_="wikitext",
                                     id="addcomment",
                                     name="addcomment",
                                     cols=80,
                                     rows=5,
                                     disabled=(not cancomment and "disabled"
                                               or None)),
                        class_="field"),
                (req.authname == 'anonymous' and tag.div(
                    tag.label("Your email or username:"******"authoraddcomment"),
                    tag.input(id="authoraddcomment",
                              type="text",
                              size=30,
                              value=authname,
                              name="authoraddcomment",
                              disabled=(not cancomment and "disabled"
                                        or None))) or None),
                tag.input(type="hidden",
                          name="__FORM_TOKEN",
                          value=req.form_token),
                tag.div(tag.input(value="Add comment",
                                  type="submit",
                                  name="submitaddcomment",
                                  size=30,
                                  disabled=(not cancomment and "disabled"
                                            or None)),
                        tag.input(value="Preview comment",
                                  type="submit",
                                  name="previewaddcomment",
                                  disabled=(not cancomment and "disabled"
                                            or None)),
                        tag.input(value="Cancel",
                                  type="submit",
                                  name="canceladdcomment",
                                  disabled=(not cancomment and "disabled"
                                            or None)),
                        class_="buttons"),
            ),
            method="post",
            action=page_url + "#commenting",
        )

        if not wikipreview:
            # Wiki edit preview already adds this javascript file
            add_script(req, 'common/js/wikitoolbar.js')

        return tag.div(the_preview, the_message, the_form, id="commenting")
Beispiel #12
0
def AddComment(macro, environ, data, *args, **kwargs):
    """Display an add comment form allowing users to post comments.

    This macro allows you to display an add comment form on the current
    page allowing users to post comments. The comments are added to the
    page's content itself.
    
    **Arguments:** //No Arguments//

    **Example(s):**
    {{{
    <<AddComment>>
    }}}

    <<AddComment>>
    """

    # Setup info and defaults
    parser = environ.parser
    request = environ.request

    page = data["page"]
    page_name = page["name"]
    page_text = page["text"]
    
    # Get the data from the POST
    comment = request.kwargs.get("comment", "")
    action = request.kwargs.get("action", "")
    author = request.kwargs.get("author", environ._user())
    
    # Ensure <<AddComment>> is not present in comment, so that infinite
    # recursion does not occur.
    comment = re.sub("(^|[^!])(\<\<AddComment)", "\\1!\\2", comment)
    
    the_preview = None
    the_comment = None

    # If we are submitting or previewing, inject comment as it should look
    if action == "preview":
        the_preview = tag.div(tag.h1("Preview"), id="preview")
        the_preview += tag.div(parser.generate(comment,
            environ=(environ, data)), class_="article")

    # When submitting, inject comment before macro
    if comment and action == "save":
        new_text = ""
        comment_text = "\n==== Comment by %s on %s ====\n\n%s\n\n" % (
                author, time.strftime('%c', time.localtime()), comment)
        for line in page_text.split("\n"):
            if line.find("<<AddComment") == 0:
                new_text += comment_text
            new_text += line + "\n"

        search = environ.search
        storage = environ.storage

        storage.reopen()
        search.update(environ)

        storage.save_text(page_name, new_text, author,
                "Comment added by %s" % author)

        search.update_page(environ.get_page(page_name), page_name,
                text=new_text)

        the_comment = tag.div(parser.generate(comment_text,
            environ=(environ, data)), class_="article")

    the_form = tag.form(
            tag.input(type="hidden", name="parent", value=page["node"]),
            tag.fieldset(
                tag.legend("Add Comment"),
                tag.p(
                    tag.textarea(
                        (not action in ("cancel", "save") and comment or ""),
                        id="comment",
                        name="comment",
                        cols=80, rows=5
                    ),
                    class_="text"
                ),
                tag.h4(tag.label("Your email or username:"******"author")),
                tag.p(
                    tag.input(id="author", name="author", type="text",
                        value=(not action in ("cancel", "save"))
                        and author or ""
                    ),
                    class_="input"
                ),
                tag.p(
                    tag.button("Preview", type="submit",
                        name="action", value="preview"),
                    tag.button("Save", type="submit",
                        name="action", value="save"),
                    tag.button("Cancel", type="submit",
                        name="action", value="cancel"),
                    class_="button"
                ),
            ),
            method="post", action=""
    )

    return tag(the_preview, the_comment, the_form)