Пример #1
0
    def expand_macro(self, formatter, name, content):
        db = self.env.get_db_cnx()

        txt = content or ''
        args = txt.split('|')
        url = args.pop(0).replace("'", "''")

        if ":" in url:
            base, name = url.split(":")
            if base != "wiki":
                return "Use 'wiki:' prefix in wiki page url", base, name
        else:
            name = url

        sql = "SELECT text from wiki where name = '%s' order by version desc limit 1" % name
        cs = db.cursor()
        cs.execute(sql)
        result = cs.fetchone()

        if not result:
            return '<b>Wiki Page %s not found!</b>' % url

        text = result[0]
        out = StringIO()
        codepage = self.env.config.get('trac', 'charset', 'ISO8859-15')

        Formatter(self.env, formatter.context).format(text, out, False)
        text = out.getvalue().encode(codepage)
        return text
Пример #2
0
    def expand_macro(self, formatter, name, content):

        env = formatter.env
        abs = env.abs_href.base
        abs = abs[:len(abs) - len(env.href.base)]
        f = Formatter(formatter.env, formatter.context)

        def convert(m):
            pre, target, suf = filter(None, m.groups())
            out = StringIO()
            f.format(target, out)
            url = re.search(HREF, out.getvalue()).groups()[0]
            # Trac creates relative links, which Markdown won't touch inside
            # <autolinks> because they look like HTML
            if pre == '<' and url != target:
                pre += abs
            return pre + str(url) + suf

        try:
            from markdown import markdown
            return markdown(re.sub(LINK, convert, content))
        except ImportError:
            msg = 'Error importing Python Markdown, install it from '
            url = 'http://www.freewisdom.org/projects/python-markdown/'
            return system_message(tag(msg, tag.a('here', href="%s" % url),
                                      '.'))
Пример #3
0
    def test_expand_macro(self):
        """ Testing the expand_macro method. """
        processor = CodeExample(self.env)
        args = 'test'
        formatter = Formatter(self.env, self.context)

        name = 'CodeExample'
        expected = '<div ' \
        'class="example">\n  <div class="title">\n\t' \
        '<span class="select_code" id="link1">' \
        'SELECT ALL</span>\n\t\n\t<span>EXAMPLE:</span>\n</div>\n    \n    ' \
        '<div class="code">' \
        '\n        <pre id="codelink1">test\n</pre>\n    </div>\n</div>'
        self.assertEqual(expected,
                         processor.expand_macro(formatter, name, args))

        args = '##type=bad\ntest'
        expected = '<div ' \
        'class="bad_example">\n  <div class="title">\n\t' \
        '<span class="select_code" id="link2">' \
        'SELECT ALL</span>\n\t\n\t<span>INCORRECT EXAMPLE:</span>\n' \
        '</div>\n    \n    <div class="code">' \
        '\n        <pre id="codelink2">test\n</pre>\n    </div>\n</div>'
        self.assertEqual(expected,
                         processor.expand_macro(formatter, name, args))

        args = '##type=good\ntest'
        expected = '<div ' \
        'class="good_example">\n  <div class="title">\n\t' \
        '<span class="select_code" id="link3">' \
        'SELECT ALL</span>\n\t\n\t<span>CORRECT EXAMPLE:</span>\n</div>' \
        '\n    \n    <div class="code">' \
        '\n        <pre id="codelink3">test\n</pre>\n    </div>\n</div>'
        self.assertEqual(expected,
                         processor.expand_macro(formatter, name, args))
Пример #4
0
 def render_macro(self, req, name, content):
     from trac.wiki.formatter import Formatter
     formatter = Formatter(self.env, req)
     def getparm(category, target):
         return req.perm.perms
     formatter.perm = getparm
     return self.expand_macro(formatter, name, content)
Пример #5
0
    def expand_macro(self, formatter, name, content):
        args, kwargs = parse_args(content)
        pattern = args[0]
        if len(args) > 1 and args[1].strip().upper() == "COMPLETED":
            completed = "AND completed>0"
        else:
            completed = "AND completed=0"
        if len(args) > 2 and args[2].strip().upper() == "ASC":
            ordering = "ASC"
        else:
            ordering = "DESC"

        db = self.env.get_db_cnx()
        cursor = db.cursor()
        print """
            SELECT name FROM milestone WHERE name %s
              %s ORDER BY name %s
            """ % (db.like(), completed, ordering)
        cursor.execute(
            """
            SELECT name FROM milestone WHERE name %s
              %s ORDER BY name %s
            """ % (db.like(), completed, ordering), (pattern, ))

        out = StringIO()
        for name, in cursor.fetchall():
            wikitext = """
                == [milestone:%(milestonename)s %(milestonename)s] ==
                [[TicketQuery(milestone=%(milestonename)s,order=id,desc=0,format=table,col=summary|owner|ticket_status|type|status)]]
                """ % {
                'milestonename': name
            }
            Formatter(self.env, formatter.context).format(wikitext, out)

        return Markup(out.getvalue())
Пример #6
0
    def process_request(self, req):
        req.perm.assert_permission('TICKET_VIEW')

        if 'id' in req.args.keys():
            try:
                ticket = int(req.args.get('id'))
            except ValueError:
                raise TracError('Need integer ticket id.')

            sql = ("SELECT 1 FROM ticket WHERE id=%s" % ticket)

            db = self.env.get_db_cnx()
            cursor = db.cursor()
            cursor.execute(sql)
            row = cursor.fetchone()
            if not row:
                raise TracError(
                    'Cannot build dependency graph for non-existent ticket %d.'
                    % ticket)

            depth = -1
            for key in req.args.keys():
                if key == 'depth':
                    depth = req.args[key]

            options = '%s,%s' % (ticket, depth)
            add_ctxtnav(req, 'Back to Ticket #%s' % ticket,
                        req.href.ticket(ticket))
            title = 'Ticket #%s Dependency Graph' % ticket
            headline = 'Dependency Graph for Ticket #%s' % ticket
        else:
            constraints = {}
            for key in req.args.keys():
                if isinstance(req.args[key], (list, tuple)):
                    constraints[key] = '|'.join(req.args[key])
                else:
                    constraints[key] = req.args[key]
            options = 'query:' + '&'.join(key + '=' + constraints[key]
                                          for key in constraints)

            title = 'Ticket query Dependency Graph'
            headline = 'Dependency Graph for Query'
            add_ctxtnav(req, 'Back to query', req.href('query', **req.args))

        data = {}

        context = Context.from_request(req, '')
        formatter = Formatter(self.env, context)
        graph = DepGraphMacro(self.env).expand_macro(formatter, 'DepGraph',
                                                     options)
        data['title'] = title
        data['headline'] = headline
        data['depgraph'] = Markup(graph)

        return 'depgraph.html', data, None
Пример #7
0
    def test_wiki_link_foreign(self):
        attachment = Attachment(self.env, 'ticket', 123)
        attachment.insert('foo.txt', tempfile.TemporaryFile(), 0)

        ns, func = AttachmentModule(self.env).get_link_resolvers().next()
        self.assertEqual('attachment', ns)

        req = Mock(path_info='/wiki')
        formatter = Formatter(self.env, req)
        self.assertEqual('<a class="attachment" title="Attachment #123: '
                         'foo.txt" href="/trac.cgi/attachment/ticket/123/'
                         'foo.txt">Foo</a>',
                         func(formatter, ns, 'ticket:123:foo.txt', 'Foo'))
Пример #8
0
    def test_wiki_link_subpage(self):
        attachment = Attachment(self.env, 'wiki', 'SomePage/SubPage')
        attachment.insert('foo.txt', tempfile.TemporaryFile(), 0)

        ns, func = AttachmentModule(self.env).get_link_resolvers().next()
        self.assertEqual('attachment', ns)

        req = Mock(path_info='/wiki/SomePage/SubPage')
        formatter = Formatter(self.env, req)
        self.assertEqual(
            '<a class="attachment" '
            'title="Attachment SomePage/SubPage: foo.txt" '
            'href="/trac.cgi/attachment/wiki/SomePage/SubPage/'
            'foo.txt">Foo</a>', func(formatter, ns, 'foo.txt', 'Foo'))
Пример #9
0
    def test_expand_macro_with_unicode(self):
        """ Testing the expand_macro method with unicode symbols. """
        processor = CodeExample(self.env)
        args = 'ТЕСТ'
        formatter = Formatter(self.env, self.context)

        name = 'CodeExample'
        expected = '<div ' \
        'class="example">\n  <div class="title">\n\t' \
        '<span class="select_code" id="link1">' \
        'SELECT ALL</span>\n\t\n\t<span>EXAMPLE:</span>\n</div>\n    \n    ' \
        '<div class="code">' \
        '\n        <pre id="codelink1">ТЕСТ\n</pre>\n    </div>\n</div>'
        self.assertEqual(expected,
                         processor.expand_macro(formatter, name, args))
Пример #10
0
    def expand_macro(self, formatter, name, content):

        env = formatter.env
        abs = env.abs_href.base
        abs = abs[:len(abs) - len(env.href.base)]
        f = Formatter(formatter.env, formatter.context)

        def convert_links(m):
            pre, target, suf = filter(None, m.groups())
            out = StringIO()
            f.format(target, out)
            url = re.search(HREF, out.getvalue()).groups()[0]
            # Trac creates relative links, which Markdown won't touch inside
            # <autolinks> because they look like HTML
            if pre == '<' and url != target:
                pre += abs
            return pre + str(url) + suf

        def emojify(html):
            pattern = ":([a-z0-9\\+\\-_]+):"
            link = "<img\
                alt=\"\\1\"\
                title=\":\\1:\"\
                height=\"20\"\
                style=\"vertical-align:middle\"\
                width=\"20\"\
                src=\"/chrome/markdown/emoji/\\1.png\" />"

            emojify_html = re.sub(pattern, link, html)
            return emojify_html

        try:
            # Import & convert
            import markdown2
            # autolink http:// n stuff
            autolinked_content = re.sub(LINK, convert_links, content)
            # convert to markdown
            html = markdown2.markdown(autolinked_content, extras=MD_EXTRAS)
            # substitute emojis
            emojified_html = emojify(html)

            return emojified_html
        except ImportError:
            # no markdown2 package found?
            msg = 'Error importing python-markdown2, install it from '
            url = 'https://github.com/trentm/python-markdown2'
            return system_message(tag(msg, tag.a('here', href="%s" % url),
                                      '.'))
Пример #11
0
    def test(self):
        """Testing WikiFormatter"""

        # Environment stub
        from trac.core import ComponentManager
        from trac.config import Configuration
        from trac.log import logger_factory
        from trac.test import InMemoryDatabase
        from trac.web.href import Href

        db = InMemoryDatabase()

        class DummyEnvironment(ComponentManager):
            def __init__(self):
                ComponentManager.__init__(self)
                self.log = logger_factory('null')
                self.config = Configuration(None)
                self.href = Href('/')
                self.abs_href = Href('http://www.example.com/')
                self._wiki_pages = {}
                self.path = ''
            def component_activated(self, component):
                component.env = self
                component.config = self.config
                component.log = self.log
            def get_db_cnx(self):
                return db

        # Load all the components that provide IWikiSyntaxProvider
        # implementations that are tested. Ideally those should be tested
        # in separate unit tests.
        import trac.versioncontrol.web_ui.browser
        import trac.versioncontrol.web_ui.changeset
        import trac.Milestone
        import trac.ticket.query
        import trac.ticket.report
        import trac.Search

        env = DummyEnvironment()
        out = StringIO.StringIO()
        Formatter(env).format(self.input, out)
        v = out.getvalue().replace('\r','')
        self.assertEquals(self.correct, v)
Пример #12
0
    def process_request(self, req):
        """Process the request. For ClearSilver, return a (template_name,
        content_type) tuple, where `template` is the ClearSilver template to use
        (either a `neo_cs.CS` object, or the file name of the template), and
        `content_type` is the MIME type of the content. For Genshi, return a
        (template_name, data, content_type) tuple, where `data` is a dictionary
        of substitutions for the template.

        For both templating systems, "text/html" is assumed if `content_type` is
        `None`.

        Note that if template processing should not occur, this method can
        simply send the response itself and not return anything.
        """
        formatter = Formatter(self.env, Context.from_request(req))
        intertrac = InterTracDispatcher(self.env)
        macro = intertrac.expand_macro(formatter, 'InterTrac', '')
        data = {'macro': macro}
        return ("intertracinfo.html", data, 'text/html')
Пример #13
0
    def test_path_recognition(self):
        """ Testing correct path requirements. """
        processor = CodeExample(self.env)
        args = '##path=test\nТЕСТ'
        formatter = Formatter(self.env, self.context)

        name = 'CodeExample'
        expected = '<div ' \
        'class="example">\n  <div class="title">\n\t' \
        '<span class="select_code" id="link1">' \
        'SELECT ALL</span>\n\t\n\t<span>EXAMPLE:</span>\n</div>\n    \n    ' \
        '<div class="system-message">\n    <strong>' \
        'During the example analyzing the following problems' \
        ' appear:</strong>\n    <ul>\n        ' \
        '<li>Path element is not found.</li>\n    '\
        '</ul>\n    </div>' \
        '\n    \n    <div class="code">' \
        '\n        <pre id="codelink1">ТЕСТ\n</pre>\n    </div>\n</div>'
        self.assertEqual(expected,
                         processor.expand_macro(formatter, name, args))
Пример #14
0
    def expand_macro(self, formatter, name, content):
        (args, kwargs) = parse_args(content, False)

        page_name = self.MACRO_PAGES + name
        page = WikiPage(self.env, page_name)
        if not page.exists:
            raise RuntimeError(u'Can\'t find page', page_name)

        for i, arg in enumerate(args):
            kwargs[unicode(i+1)] = arg

        text = RelaxedIdTemplate(page.text).safe_substitute(kwargs)

        out = StringIO()
        Formatter(self.env, formatter.context).format(text, out)

        out = out.getvalue().strip()
        if out.startswith(u'<p>'): out = out[3:]
        if out.endswith(u'</p>'): out = out[:-4]
        return out
Пример #15
0
    def test_macro_with_invalid_lang(self):
        """ Testing the expand_macro method with invalid language. """
        processor = CodeExample(self.env)
        args = '#!python1\ntest'
        formatter = Formatter(self.env, self.context)

        name = 'CodeExample'
        expected = '<div ' \
        'class="example">\n  <div class="title">\n\t' \
        '<span class="select_code" id="link1">' \
        'SELECT ALL</span>\n\t\n\t<span>EXAMPLE:</span>\n</div>\n    \n    ' \
        '<div class="system-message">\n    <strong>' \
        'During the example analyzing the following problems appear:' \
        '</strong>\n    ' \
        '<ul>\n        <li>no lexer for alias \'python1\' found</li>' \
        '\n    </ul>\n    </div>\n    \n    ' \
        '<div class="code">' \
        '\n        <pre id="codelink1">test\n</pre>\n    </div>\n</div>'
        self.assertEqual(expected,
                         processor.expand_macro(formatter, name, args))
Пример #16
0
    def pre_process_request(self, req, handler):
        if req.path_info.startswith('/wiki'):
            if req.method == 'POST' and req.args.get('action',
                                                     'view') == 'view':
                post_handler = None
                for poster in self.macro_posters:
                    if not hasattr(poster, 'match_macro_post'): continue
                    rv = poster.match_macro_post(req)
                    if isinstance(rv, (str, unicode)):
                        rv = rv in req.args.keys()
                    if rv:
                        post_handler = poster
                        break
                if post_handler:
                    post_handler.process_macro_post(req)
                else:
                    # Silly stuff here
                    self.log.debug(
                        'MacroPostModule: Unclaimed POST, scanning page %s',
                        req.path_info[6:])
                    page = WikiPage(self.env, req.path_info[6:])
                    matches = self.macro_re.findall(
                        page.text) + self.proc_re.findall(page.text)
                    for name in matches:
                        self.log.debug('MacroPostModule: Found macro "%s"',
                                       name)
                        resource = Resource('wiki', name)
                        context = Context.from_request(req, resource)
                        wp = WikiProcessor(Formatter(self.env, context), name)
                        if wp.macro_provider is None:
                            self.log.debug(
                                'MacroPostModule: Invalid name!!! How did that happen'
                            )
                            continue
                        if hasattr(wp.macro_provider, 'process_macro_post') and \
                           not hasattr(wp.macro_provider, 'match_macro_post'):
                            wp.macro_provider.process_macro_post(req)
                req.environ['REQUEST_METHOD'] = 'GET'  # Revert back to a GET

        return handler
Пример #17
0
    def process_request(self, req):
        req.perm.require('TAGS_VIEW')
        add_ctxtnav(req, 'Cloud', req.href.tags())
        match = re.match(r'/tags/?(.*)', req.path_info)
        if match.group(1):
            req.redirect(req.href('tags', q=match.group(1)))
        add_stylesheet(req, 'tags/css/tractags.css')
        query = req.args.get('q', '')
        data = {'title': 'Tags'}
        formatter = Formatter(self.env,
                              Context.from_request(req, Resource('tag')))

        realms = [p.get_taggable_realm() for p in self.tag_providers]
        checked_realms = [r for r in realms if r in req.args] or realms
        data['tag_realms'] = [{
            'name': realm,
            'checked': realm in checked_realms
        } for realm in realms]

        if query:
            data['tag_title'] = 'Showing objects matching "%s"' % query
        data['tag_query'] = query

        from tractags.macros import TagCloudMacro, ListTaggedMacro
        if not query:
            macro = TagCloudMacro(self.env)
        else:
            macro = ListTaggedMacro(self.env)
        query = '(%s) (%s)' % (' or '.join(
            ['realm:' + r for r in realms if r in checked_realms]), query)
        self.env.log.debug('Tag query: %s', query)
        try:
            data['tag_body'] = macro.expand_macro(formatter, None, query)
        except InvalidQuery, e:
            data['tag_query_error'] = to_unicode(e)
            data['tag_body'] = TagCloudMacro(self.env) \
                .expand_macro(formatter, None, '')
Пример #18
0
    def filter_stream(self, req, method, filename, stream, data):
        """Return a filtered Genshi event stream, or the original unfiltered
        stream if no match.

        `req` is the current request object, `method` is the Genshi render
        method (xml, xhtml or text), `filename` is the filename of the template
        to be rendered, `stream` is the event stream and `data` is the data for
        the current template.

        See the Genshi documentation for more information.
        """

        if filename in ('ticket.html', 'agilo_ticket_new.html',):

            add_stylesheet(req, 'tags/css/tractags.css')
            add_stylesheet(req, 'loomingclouds/css/tagcloud.css')
            add_script(req, 'loomingclouds/js/tag_filler.js')
            formatter = Formatter(self.env, Context.from_request(req))
            macro = TagCloudMacro(self.env)
            cloud = macro.expand_macro(formatter, 'TagCloud', '')

            stream |= Transformer("//input[@id='field-keywords']").after(cloud).after(tag.a('More...',href='#',class_='tag-cloud-filler'))

        return stream
Пример #19
0
    def process_request(self, req):
        req.perm.require('TAGS_VIEW')

        match = re.match(r'/tags/?(.*)', req.path_info)
        tag_id = match.group(1) and match.group(1) or None
        query = req.args.get('q', '')

        # Consider only providers, that are permitted for display.
        tag_system = TagSystem(self.env)
        all_realms = tag_system.get_taggable_realms(req.perm)
        if not (tag_id or query) or [r for r in all_realms if r in req.args
                                     ] == []:
            for realm in all_realms:
                if not realm in self.exclude_realms:
                    req.args[realm] = 'on'
        checked_realms = [r for r in all_realms if r in req.args]
        if query:
            # Add permitted realms from query expression.
            checked_realms.extend(query_realms(query, all_realms))
        realm_args = dict(
            zip([r for r in checked_realms], ['on' for r in checked_realms]))
        # Switch between single tag and tag query expression mode.
        if tag_id and not re.match(r"""(['"]?)(\S+)\1$""", tag_id, re.UNICODE):
            # Convert complex, invalid tag ID's --> query expression.
            req.redirect(req.href.tags(realm_args, q=tag_id))
        elif query:
            single_page = re.match(r"""(['"]?)(\S+)\1$""", query, re.UNICODE)
            if single_page:
                # Convert simple query --> single tag.
                req.redirect(req.href.tags(single_page.group(2), realm_args))

        data = dict(page_title=_("Tags"), checked_realms=checked_realms)
        # Populate the TagsQuery form field.
        data['tag_query'] = tag_id and tag_id or query
        data['tag_realms'] = list(
            dict(name=realm, checked=realm in checked_realms)
            for realm in all_realms)
        if tag_id:
            data['tag_page'] = WikiPage(self.env,
                                        tag_system.wiki_page_prefix + tag_id)
        if query or tag_id:
            macro = 'ListTagged'
            # TRANSLATOR: The meta-nav link label.
            add_ctxtnav(req, _("Back to Cloud"), req.href.tags())
            args = "%s,format=%s,cols=%s" % \
                   (tag_id and tag_id or query, self.default_format,
                    self.default_cols)
            data['mincount'] = None
        else:
            macro = 'TagCloud'
            mincount = as_int(req.args.get('mincount', None),
                              self.cloud_mincount)
            args = mincount and "mincount=%s" % mincount or None
            data['mincount'] = mincount
        formatter = Formatter(self.env,
                              Context.from_request(req, Resource('tag')))
        self.env.log.debug("%s macro arguments: %s" %
                           (macro, args and args or '(none)'))
        macros = TagWikiMacros(self.env)
        try:
            # Query string without realm throws 'NotImplementedError'.
            data['tag_body'] = checked_realms and \
                               macros.expand_macro(formatter, macro, args,
                                                   realms=checked_realms) \
                               or ''
        except InvalidQuery, e:
            data['tag_query_error'] = to_unicode(e)
            data['tag_body'] = macros.expand_macro(formatter, 'TagCloud', '')
Пример #20
0
 def wiki(self, text):
     out = StringIO.StringIO()
     Formatter(self.formatter.env, self.formatter.context).format(text, out)
     return out.getvalue()
Пример #21
0
 def formatter(self, env):
     return Formatter(env)
Пример #22
0
 def code_formatter(env, context, language, text):
     processor = WikiProcessor(Formatter(env, context), language)
     html = processor.process(text)
     raw = nodes.raw('', html, format='html')
     return raw
Пример #23
0
 def formatter(self):
     return Formatter(self.env, self.req)
Пример #24
0
    def expand_macro(self, formatter, name, args):
        u"""パラメータを展開する。パラメータは、カンマで区切ることとする。
        パラメータのキーと値は以下のような感じで定義する(キーと値は":"でつなぐ)
        x -> 横軸の表示内容(抽出内容)を"|"で区切ってセット。
             なお、表示対象とするフィールド名は先頭に記載し、具体的な値は"="でつなぐ。値を省略した場合は項目の一覧を自動取得。
             グループ化したいときは "+"でつなぐ。改名したいときは AS で別名をつける。
             例)x:status=new|accepted + assigned AS doing|closed|reopened
        y -> 縦軸の表示内容。設定方法はxと同じ
        q -> 抽出条件(SQLのWHERE条件)。複数の条件を指定する場合は"&"でつなぐ。
             q:milestone=milestone1&owner=hoge
        xa-> x軸部分をクリックした際に表示するカスタムクエリのorderおよびgroup指定。
             xa:order=id&group=status のような感じで指定する。指定がない場合はorder=idのみを自動的に付加する。
        ya-> y軸部分をクリックした際に表示するカスタムクエリのorderおよびgroup指定。
             指定方法はxaと同様。
        m -> 表部分をクリックした際に表示するカスタムクエリのorderおよびgroup指定。
             指定方法はxa/yaと同様。
        """

        # とりあえず、パラメータ中に";"が含まれている場合はエラーとする
        if ';' in args:
            raise TracError('Parameter Error')

        # パラメータをカンマで区切って展開
        # ":"でキーと値に分割してDictionaryに格納(":"で2つに分割できなかったものは処理対象外)
        params = {}
        for value in args.split(','):
            v = value.split(':')
            if len(v) == 2:
                params[v[0]] = v[1]

        # 抽出条件を構築(SQLのWHERE節を構築)
        condition = self.createcondition(params)

        # x軸(横軸)の処理
        xaxiswork = params['x'].split('=')
        xaxiskey = xaxiswork[0]
        xaxiscolname = xaxiskey

        # y軸(縦軸)の処理
        yaxiswork = params['y'].split('=')
        yaxiskey = yaxiswork[0]
        yaxiscolname = yaxiskey

        # Ticketのフィールド一覧を取得する
        xfield = None
        yfield = None
        for field in TicketSystem(self.env).get_ticket_fields():
            if field['name'] == xaxiskey:
                xfield = field
                xaxislabel = xfield['label']
            if field['name'] == yaxiskey:
                yfield = field
                yaxislabel = yfield['label']

        # それぞれの軸がカスタムフィールドか否か
        xcustom = 'custom' in xfield and xfield['custom']
        ycustom = 'custom' in yfield and yfield['custom']
        if xcustom:
            xaxiskey = 'cx.value'
        if ycustom:
            yaxiskey = 'cy.value'

        yaxis = self.getaxisvalues(yaxiswork, yfield, ycustom, yaxiskey, yaxiscolname, condition)
        xaxis = self.getaxisvalues(xaxiswork, xfield, xcustom, xaxiskey, xaxiscolname, condition)

        if len(xaxis) == 0 or len(yaxis) == 0:
            return u'<ul><i>抽出条件に合致するチケットが存在しませんでした</i></ul>'

        query = u'SELECT '
        query += 'CASE '
        for y in yaxis:
            query += 'when %s in (%s) then \'%s\' \n' % (yaxiskey, ",".join(["'%s'" % v.strip() for v in y.split("+")]), y)
        query += 'END as %s' % yaxiskey

        for x in xaxis:
            query += ",sum(case when coalesce(%s,'') IN (%s) then 1 else 0 end)" % (xaxiskey, ",".join(["'%s'" % v.strip() for v in x.split("+")]))
        query += " from ticket "

        # カスタムフィールドを使用している場合はticket_customテーブルを連結する必要あり
        # なお、カスタムフィールドの場合は取得する際の列名がいったんvalueに置き換わってしまうので注意
        if xcustom:
            query += " left outer join ticket_custom as cx on cx.ticket=id and cx.name='%s'" % xaxiscolname
        if ycustom:
            query += " left outer join ticket_custom as cy on cy.ticket=id and cy.name='%s'" % yaxiscolname

        # 条件文及びgroup値を追加
        query += " %s group by %s" % (condition, yaxiskey)

        self.env.log.info(query)

        result = {}
        for row in self.env.db_query(query):
            result[row[0] or ''] = row[1:]

        # queryリンクのパラメータの各要素を構築する
        querycond = 'q' in params and "&%s" % params['q'] or '&order=priority'
        xquery = 'xa' in params and "&%s" % params['xa'] or "&order=id"
        yquery = 'ya' in params and "&%s" % params['ya'] or "&order=id"
        mquery = 'm' in params and "&%s" % params['m'] or "&order=id"

        # 出力テキスト構築
        # x軸のタイトル行を構築する
        xaxislabels = [(yaxislabel + u'\' + xaxislabel)] + xaxiswork[1] + [u"小計"]
        wikitext = "||%s||\n" % "||".join(["= %s =" % x for x in xaxislabels])

        # 縦計を格納する
        ysum = {}
        for x in xaxis:
            ysum[x] = 0
        for yindex, y in enumerate(yaxis):
            # タイトル列
            wikitext += "||= %s =||" % yaxiswork[1][yindex]
            if y in result:
                each = result[y]
                linesum = 0
                for cnt2, x in enumerate(xaxis):
                    # テーブル部分本体
                    eachval = each[cnt2]
                    wikitext += self.q_or_0("%s=%s&%s=%s%s%s", (yaxiscolname, y, xaxiscolname, x, querycond, mquery), each[cnt2])
                    linesum += eachval
                    ysum[x] += eachval
                # 小計列
                wikitext += self.q_or_0("%s=%s%s%s", (yaxiscolname, y, querycond, yquery), linesum, term="\n")
            else:
                # 該当するy軸に対応するデータがない場合はリンクは付加しない
                for x in xaxis:
                    wikitext += "0||"
                wikitext += "0||\n"

        # 合計行
        wikitext += "||= %s =||" % u"【合計】"
        linesum = 0
        for x in xaxis:
            ysumval = ysum[x]
            wikitext += self.q_or_0("%s=%s%s%s", (xaxiscolname, x, querycond, xquery), ysum[x])
            linesum += ysumval
        # 総合計
        wikitext += self.q_or_0("%s", (querycond[1:],), linesum, term="\n")

        # 構築したwikiテキストをhtmlに変換(expand_macroの戻り値はhtmlそのものとなる)。
        out = StringIO()
        Formatter(self.env, formatter.context).format(wikitext, out)
        return Markup(out.getvalue())
Пример #25
0
    def process_request(self, req):
        req.perm.require('TAGS_VIEW')

        match = re.match(r'/tags/?(.*)', req.path_info)
        tag_id = match.group(1) and match.group(1) or None
        query = req.args.get('q', '')

        realms = [p.get_taggable_realm() for p in self.tag_providers
                  if (not hasattr(p, 'check_permission') or \
                      p.check_permission(req.perm, 'view'))]
        if not (tag_id or query) or [r for r in realms if r in req.args] == []:
            for realm in realms:
                if not realm in self.exclude_realms:
                    req.args[realm] = 'on'
        checked_realms = [r for r in realms if r in req.args]
        realm_args = dict(
            zip([r for r in checked_realms], ['on' for r in checked_realms]))
        if tag_id and not re.match(r"""(['"]?)(\S+)\1$""", tag_id, re.UNICODE):
            # Convert complex, invalid tag ID's to query expression.
            req.redirect(req.href.tags(realm_args, q=tag_id))
        elif query:
            single_page = re.match(r"""(['"]?)(\S+)\1$""", query, re.UNICODE)
            if single_page:
                # Convert simple query for single tag ID.
                req.redirect(req.href.tags(single_page.group(2), realm_args))

        data = dict(page_title=_("Tags"), checked_realms=checked_realms)
        # Populate the TagsQuery form field.
        data['tag_query'] = tag_id and tag_id or query
        data['tag_realms'] = list(
            dict(name=realm, checked=realm in checked_realms)
            for realm in realms)
        if tag_id:
            page_name = tag_id
            page = WikiPage(self.env, page_name)
            data['tag_page'] = page

        macros = TagWikiMacros(self.env)
        if query or tag_id:
            # TRANSLATOR: The meta-nav link label.
            add_ctxtnav(req, _("Back to Cloud"), req.href.tags())
            macro = 'ListTagged'
            args = '%s,format=%s,cols=%s,realm=%s' \
                   % (tag_id and tag_id or query, self.default_format,
                      self.default_cols, '|'.join(checked_realms))
            data['mincount'] = None
        else:
            macro = 'TagCloud'
            mincount = as_int(req.args.get('mincount', None),
                              self.cloud_mincount)
            args = 'mincount=%s,realm=%s' % (mincount,
                                             '|'.join(checked_realms))
            data['mincount'] = mincount
        formatter = Formatter(self.env,
                              Context.from_request(req, Resource('tag')))
        self.env.log.debug('Tag macro arguments: %s', args)
        try:
            # Query string without realm throws 'NotImplementedError'.
            data['tag_body'] = len(checked_realms) > 0 and \
                               macros.expand_macro(formatter, macro, args) \
                               or ''
        except InvalidQuery, e:
            data['tag_query_error'] = to_unicode(e)
            data['tag_body'] = macros.expand_macro(formatter, 'TagCloud', '')
Пример #26
0
    def expand_macro(self, formatter, name, args):
        """
        Return a list of translated pages with the native language names.
        The list of languages supported can be configured by adding new
        entries to TracLanguages page. Refer to ISO 639-1 for more information.
        """

        args, kw = parse_args(args)

        # first handle special cases
        show = u""
        lang = None
        silent = u'silent' in args
        outdated = u""
        if u'lang' in kw:
            lang = kw[u'lang']
        if u'outdated' in kw:
            outdated = self.outdated_tx % kw[u'outdated']
        if u'showproblems' in args:
            show += self._get_problems(silent)
        if u'showstatus' in args:
            show += self._get_status(lang)
        if u'showoutdated' in args:
            label = None
            if u'label_outdated' in kw:
                label = kw[u'label_outdated']
            show += self._get_outdated(lang, label)
        if u'showmissing' in args:
            show += self._get_missing(lang)
        if u'showuntranslated' in args:
            show += self._get_untranslated(silent)
        if len(show):
            outshow = StringIO()
            Formatter(self.env, formatter.context).format(show, outshow)
            val = outshow.getvalue()
            val = re.sub('>\$\$\$([a-z]+?)\$\$\$<a class=".*?"', \
                ' style="background-color:\\1"><a style="color:#151B8D"', val)
            # try again more secure in case previous fails due to Wiki engine changes
            val = re.sub('>\$\$\$([a-z]+?)\$\$\$', \
                ' style="background-color:\\1">', val)
            return val

        page_name = formatter.context.resource.id
        prefix, base_page_name, lang_code = self._get_page_info(page_name)

        lang_link_list = []
        for translation in self._get_translations(prefix, base_page_name):
            if translation != lang_code:
                page_name = self._get_translated_page(prefix, base_page_name,
                                                      translation)
                lang_link_list.append(u"  * [[wiki:/%s|%s]]" % (page_name, \
                    self._get_language_name(translation)))
            else:
                lang_link_list.append(u"  * '''%s'''" %
                                      self._get_language_name(translation))

        baselink = ""
        if lang_code != self.base_lang and u'revision' in kw:
            basepage = self._get_translated_page(prefix, base_page_name,
                                                 self.base_lang)
            newver = WikiPage(self.env, basepage).version
            oldver = abs(int(kw[u'revision']))
            if oldver < newver:
                baselink = u"\n  * [[wiki:/%s?action=diff&old_version=%s|@%s - @%s]]" \
                    % (basepage, oldver, oldver, newver)

        if len(lang_link_list) <= 1:
            return outdated
        out = StringIO()
        Formatter(self.env, formatter.context).format(u'\n'.join(lang_link_list) \
            +baselink, out)

        desc = u"Languages"
        if self.description.has_key(lang_code):
            desc = self.description[lang_code]
        return outdated + u"""
<div class="wiki-toc trac-nav" style="clear:both">
<h4>%s:</h4>
%s
</div>""" % (desc, out.getvalue())
Пример #27
0
    def process_request(self, req):
        req.perm.require('TAGS_VIEW')

        match = re.match(r'/tags/?(.*)', req.path_info)
        tag_id = match.group(1) and match.group(1) or None
        query = req.args.get('q', '')

        # Consider only providers, that are permitted for display.
        tag_system = TagSystem(self.env)
        all_realms = tag_system.get_taggable_realms(req.perm)
        if not (tag_id or query) or [r for r in all_realms
                                     if r in req.args] == []:
            for realm in all_realms:
                if realm not in self.exclude_realms:
                    req.args[realm] = 'on'
        checked_realms = [r for r in all_realms if r in req.args]
        if query:
            # Add permitted realms from query expression.
            checked_realms.extend(query_realms(query, all_realms))
        realm_args = dict(zip([r for r in checked_realms],
                              ['on' for r in checked_realms]))
        # Switch between single tag and tag query expression mode.
        if tag_id and not re.match(r"""(['"]?)(\S+)\1$""", tag_id, re.UNICODE):
            # Convert complex, invalid tag ID's --> query expression.
            req.redirect(req.href.tags(realm_args, q=tag_id))
        elif query:
            single_page = re.match(r"""(['"]?)(\S+)\1$""", query, re.UNICODE)
            if single_page:
                # Convert simple query --> single tag.
                req.redirect(req.href.tags(single_page.group(2), realm_args))

        data = dict(page_title=_("Tags"), checked_realms=checked_realms)
        # Populate the TagsQuery form field.
        data['tag_query'] = tag_id and tag_id or query
        data['tag_realms'] = list(dict(name=realm,
                                       checked=realm in checked_realms)
                                  for realm in all_realms)
        if tag_id:
            data['tag_page'] = WikiPage(self.env,
                                        tag_system.wiki_page_prefix + tag_id)
        if query or tag_id:
            macro = 'ListTagged'
            # TRANSLATOR: The meta-nav link label.
            add_ctxtnav(req, _("Back to Cloud"), req.href.tags())
            args = "%s,format=%s,cols=%s" % \
                   (tag_id and tag_id or query, self.default_format,
                    self.default_cols)
            data['mincount'] = 0
        else:
            macro = 'TagCloud'
            mincount = as_int(req.args.get('mincount', 0),
                              self.cloud_mincount)
            args = mincount and "mincount=%s" % mincount or None
            data['mincount'] = mincount

        # When using the given req the page isn't rendered properly. The call
        # to expand_macro() leads to Chrome().render_template(req, ...).
        # The function render_template() breaks something in the request handling.
        # That used to work with Genshi.
        #
        # With this mocked req everything is just fine.
        mock_req = MockRequest(self.env, path_info=req.path_info,
                           authname=req.authname, script_name=req.href())
        formatter = Formatter(self.env, web_context(mock_req, Resource('tag')))
        self.env.log.debug("%s macro arguments: %s", macro,
                           args and args or '(none)')
        macros = TagWikiMacros(self.env)
        try:
            # Query string without realm throws 'NotImplementedError'.
            data['tag_body'] = checked_realms and \
                               macros.expand_macro(formatter, macro, args,
                                                   realms=checked_realms) \
                               or ''
            data['tag_body'] = Markup(to_unicode(data['tag_body']))
        except InvalidQuery as e:
            data['tag_query_error'] = to_unicode(e)
            data['tag_body'] = macros.expand_macro(formatter, 'TagCloud', '')

        data['realm_args'] = realm_args
        add_stylesheet(req, 'tags/css/tractags.css')
        return 'tag_view.html', data, {'domain': 'tractags'}
Пример #28
0
    def convert_content(self, req, input_type, source, output_type):

        # get parameters from trac ini file
        self.img_max_x = self.env.config.get('pagetodoc', 'img_max_x', self.img_max_x)
        self.img_max_y = self.env.config.get('pagetodoc', 'img_max_y', self.img_max_y)
        self.img_max_y = self.env.config.get('pagetodoc', 'dpi', self.dpi)

        # XSL-Transformation        
        xsltfilepath = self.env.config.get('pagetodoc', 'xsltfile', '')
        # TBD: Fehler ausgeben, wenn xsltfile nicht gelesen werden kann
        # TBD: Parameter aus der trac.ini an zentraler Stelle auslesen
        if xsltfilepath == '':
            message = "You have to set the 'xsltfile' option in the " \
                "[pagetodoc] section in trac.ini"
            raise_dependency_issue(message, req, self.env)
        if not os.path.exists(xsltfilepath):
            message = ("Value for 'xsltfile' in the [pagetodoc] section in " \
                "trac.ini does not exist: '%s'.")% xsltfilepath
            raise_dependency_issue(message, req, self.env)

        # maybe for later use
        #codepage = self.env.config.get('trac', 'charset', 'iso-8859-1')
        codepage = 'iso-8859-1'

        # Convert Wiki markup to HTML, new style
        out = StringIO()
        context = Context.from_request(req, 'wiki', req.path_info[6:])
        Formatter(self.env, context).format(source, out)
        html = Markup(out.getvalue()).encode(codepage, 'replace')

        # remove the bad HTML produced by the breadcrumbs plugin
        # RFE: find a universal way to do this
        html = re.compile('(<lh[^>]*>)').sub('', html)

        # temporary files and folders
        self.tempdir = mkdtemp(prefix="page2doc")
        htmlfilehandle, htmlfilepath = mkstemp(prefix='trac_', dir=self.tempdir, suffix = ".html")
        wordfilehandle, wordfilepath = mkstemp(prefix='word_', dir=self.tempdir, suffix = ".doc")
        os.close(wordfilehandle)

        # for debug: set all rights
        #self.chmod_tmp_dir(self.tempdir)

        # images
        # replace href with absolute path and if existing, base auth login
        try:
            # this will work if the authentication type is basic (and not over SSL?)
            login = base64.b64decode(req.environ['HTTP_AUTHORIZATION'][6:]) + '@'                  
        except (KeyError, TypeError):
            login = ''
                   
        html = re.sub('<img src="(?!\w+://)', '<img src="%s://%s%s:%d' % (req.scheme, login, req.server_name, req.server_port), html)

        # save images to disk
        html = re.sub('<img src="([^"]*)"', self.download_image, html)

        # write HTML page to disk
        os.write(htmlfilehandle, '<html><body>' + html + '</body></html>')
        os.close(htmlfilehandle)

        # clean up the HTML page using HTML Tidy
        args = '-m -asxhtml -latin1 --doctype omit'
        tidypath = self.env.config.get('pagetodoc', 'tidypath', 'tidy')

        # verify that Tidy exists and is setup correctly
        tidy_error = dependency_failure("tidy", tidypath, "-v")

        if tidy_error:
            raise_dependency_issue(tidy_error, req, self.env)

        cmd = '"%s" %s %s' % (tidypath, args, htmlfilepath)
        self.execute_external_program(cmd)

        # workaround namespace
        self.perform_workarounds(htmlfilepath, 'html')

        if self.verbose:
            verb = '-v'
        else:
            verb = ''
        xsltprocpath = self.env.config.get('pagetodoc', 'xsltprocpath', 'xsltproc')

        # verify that Tidy exists and is setup correctly
        xsltproc_error = dependency_failure("xsltproc", xsltprocpath, "-V")

        if xsltproc_error:
            raise_dependency_issue(xsltproc_error, req, self.env)

        cmd = '%s %s --html -o %s %s %s' % (
            xsltprocpath, verb, wordfilepath, xsltfilepath, htmlfilepath)
        self.execute_external_program(cmd)

        # workaround pre-tags
        self.perform_workarounds(wordfilepath, 'pre')

        zipfilepath = os.path.join(
            self.tempdir, os.path.basename(str(req.path_info) + '.zip'))
            
        # create a zip file and store all files into it      
        zipfilehandle = zipfile.ZipFile(zipfilepath, "w")
        zipfilehandle.write(wordfilepath, os.path.basename(str(req.path_info) + '.htm'))       
        for image in self.images:
            zipfilehandle.write(image, self.imagesubdir + os.path.basename(image))     
        zipfilehandle.close()
        zip_file = open(zipfilepath, "rb")
        zip = zip_file.read()
        zip_file.close()

        # delete temporary folders and files
        self.remove_dir(os.path.join(self.tempdir, self.logsubdir))
        self.remove_dir(os.path.join(self.tempdir, self.imagesubdir))
        self.remove_dir(self.tempdir)

        # reset image list
        self.images = []

        return (zip, 'application/zip')
Пример #29
0
    def process_request(self, req):
        """Process the request. For ClearSilver, return a (template_name,
        content_type) tuple, where `template` is the ClearSilver template to use
        (either a `neo_cs.CS` object, or the file name of the template), and
        `content_type` is the MIME type of the content. For Genshi, return a
        (template_name, data, content_type) tuple, where `data` is a dictionary
        of substitutions for the template.

        For both templating systems, "text/html" is assumed if `content_type` is
        `None`.

        Note that if template processing should not occur, this method can
        simply send the response itself and not return anything.
        """

        # get the GeoTicket component
        assert self.env.is_component_enabled(GeoTicket)
        geoticket = GeoTicket(self.env)

        # add the query script
        add_script(req, 'common/js/query.js')

        # get the panel configuration
        config = self.panels()

        # build the panels
        panels = []
        located_tickets = geoticket.tickets_with_location()
        for panel in config:

            # query the tickets
            query_string = panel['query']
            query = Query.from_string(self.env, query_string)

            # decide the date to sort by
            if query.order == 'time':
                date_to_display = 'time_created'
            else:
                date_to_display = 'time_changed'
            results = query.execute(req)
            n_tickets = len(results)
            results = [
                result for result in results if result['id'] in located_tickets
            ]
            locations = []
            tickets = []
            results = results[:self.dashboard_tickets]
            for result in results:
                ticket = Ticket(self.env, result['id'])
                try:

                    address, (lat, lon) = geoticket.locate_ticket(ticket)
                    content = geoticket.feature_content(req, ticket)

                    # style for the markers
                    style = {}
                    for extension in self.marker_style:
                        style.update(extension.style(ticket, req, **style))
                    style = style or None

                    locations.append({
                        'latitude': lat,
                        'longitude': lon,
                        'style': style,
                        'content': Markup(content)
                    })
                    tickets.append(ticket)
                except GeolocationException:
                    continue

            title = panel['label']
            panels.append({
                'title': title,
                'id': panel['id'],
                'locations': Markup(simplejson.dumps(locations)),
                'tickets': tickets,
                'n_tickets': n_tickets,
                'date_to_display': date_to_display,
                'query_href': query.get_href(req.href)
            })

        # add the tag cloud, if enabled
        cloud = None
        if self.display_cloud:
            if TagCloudMacro is None:
                self.log.warn(
                    "[geo] display_cloud is set but the TagsPlugin is not installed"
                )
            else:
                formatter = Formatter(self.env, Context.from_request(req))
                macro = TagCloudMacro(self.env)
                cloud = macro.expand_macro(formatter, 'TagCloud', '')
                add_stylesheet(req, 'tags/css/tractags.css')
                add_stylesheet(req, 'tags/css/tagcloud.css')

        # compile data for the genshi template
        data = dict(panels=panels,
                    cloud=cloud,
                    openlayers_url=self.openlayers_url)
        return ('mapdashboard.html', data, 'text/html')