| | 59 | |
|---|
| | 60 | # Content conversion insanity |
|---|
| | 61 | def process_request(self, req): |
|---|
| | 62 | constraints = QueryModule(self.env)._get_constraints(req) |
|---|
| | 63 | if not constraints and not req.args.has_key('order'): |
|---|
| | 64 | # avoid displaying all tickets when the query module is invoked |
|---|
| | 65 | # with no parameters. Instead show only open tickets, possibly |
|---|
| | 66 | # associated with the user |
|---|
| | 67 | constraints = {'status': ('new', 'assigned', 'reopened')} |
|---|
| | 68 | if req.authname and req.authname != 'anonymous': |
|---|
| | 69 | constraints['owner'] = (req.authname,) |
|---|
| | 70 | else: |
|---|
| | 71 | email = req.session.get('email') |
|---|
| | 72 | name = req.session.get('name') |
|---|
| | 73 | if email or name: |
|---|
| | 74 | constraints['cc'] = ('~%s' % email or name,) |
|---|
| | 75 | |
|---|
| | 76 | query = Query(self.env, constraints, req.args.get('order'), |
|---|
| | 77 | req.args.has_key('desc'), req.args.get('group'), |
|---|
| | 78 | req.args.has_key('groupdesc'), |
|---|
| | 79 | req.args.has_key('verbose')) |
|---|
| | 80 | |
|---|
| | 81 | format = req.args.get('format') |
|---|
| | 82 | self.send_converted(req, 'trac.ticket.Query', query, format, 'query') |
|---|
| | 83 | |
|---|
| | 84 | def get_supported_conversions(self): |
|---|
| | 85 | yield ('csv', 'Comma-delimited Text', 'csv', |
|---|
| | 86 | 'trac.ticket.Query', 'text/csv', 9) |
|---|
| | 87 | |
|---|
| | 88 | def convert_content(self, req, mimetype, query, key): |
|---|
| | 89 | if key == 'rss': |
|---|
| | 90 | return self.export_rss(req, query) + ('rss',) |
|---|
| | 91 | elif key == 'csv': |
|---|
| | 92 | return self.export_csv(req, query, mimetype='text/csv') + ('csv',) |
|---|
| | 93 | elif key == 'tab': |
|---|
| | 94 | return self.export_csv(req, query, '\t', 'text/tab-separated-values') + ('tsv',) |
|---|
| | 95 | |
|---|
| | 96 | def send_converted(self, req, in_type, content, selector, filename='file'): # Stolen from Mimetype |
|---|
| | 97 | """Helper method for converting `content` and sending it directly. |
|---|
| | 98 | |
|---|
| | 99 | `selector` can be either a key or a MIME Type.""" |
|---|
| | 100 | from trac.web import RequestDone |
|---|
| | 101 | content, output_type, ext = self.convert_content(req, in_type, |
|---|
| | 102 | content, selector) |
|---|
| | 103 | req.send_response(200) |
|---|
| | 104 | req.send_header('Content-Type', output_type) |
|---|
| | 105 | req.send_header('Content-Disposition', 'filename=%s.%s' % (filename, |
|---|
| | 106 | ext)) |
|---|
| | 107 | req.end_headers() |
|---|
| | 108 | req.write(content) |
|---|
| | 109 | raise RequestDone |
|---|
| | 110 | |
|---|
| | 111 | # Hacked content converters |
|---|
| | 112 | def export_csv(self, req, query, sep=',', mimetype='text/plain'): |
|---|
| | 113 | self.log.debug('PrivateTicket: Running hacked CSV converter') |
|---|
| | 114 | content = StringIO() |
|---|
| | 115 | cols = query.get_columns() |
|---|
| | 116 | content.write(sep.join([col for col in cols]) + CRLF) |
|---|
| | 117 | |
|---|
| | 118 | fn = PrivateTicketsSystem(self.env).check_ticket_access |
|---|
| | 119 | results = query.execute(req, self.env.get_db_cnx()) |
|---|
| | 120 | for result in results: |
|---|
| | 121 | # Filter data |
|---|
| | 122 | if not fn(req, result['id']): |
|---|
| | 123 | continue |
|---|
| | 124 | |
|---|
| | 125 | content.write(sep.join([unicode(result[col]).replace(sep, '_') |
|---|
| | 126 | .replace('\n', ' ') |
|---|
| | 127 | .replace('\r', ' ') |
|---|
| | 128 | for col in cols]) + CRLF) |
|---|
| | 129 | return (content.getvalue(), '%s;charset=utf-8' % mimetype) |
|---|
| | 130 | |
|---|
| | 131 | def export_rss(self, req, query): |
|---|
| | 132 | query.verbose = True |
|---|
| | 133 | db = self.env.get_db_cnx() |
|---|
| | 134 | fn = PrivateTicketsSystem(self.env).check_ticket_access |
|---|
| | 135 | results = [r for r in query.execute(req, db) if fn(req, r['id'])] |
|---|
| | 136 | for result in results: |
|---|
| | 137 | result['href'] = req.abs_href.ticket(result['id']) |
|---|
| | 138 | if result['reporter'].find('@') == -1: |
|---|
| | 139 | result['reporter'] = '' |
|---|
| | 140 | if result['description']: |
|---|
| | 141 | # unicode() cancels out the Markup() returned by wiki_to_html |
|---|
| | 142 | descr = wiki_to_html(result['description'], self.env, req, db, |
|---|
| | 143 | absurls=True) |
|---|
| | 144 | result['description'] = unicode(descr) |
|---|
| | 145 | if result['time']: |
|---|
| | 146 | result['time'] = http_date(result['time']) |
|---|
| | 147 | req.hdf['query.results'] = results |
|---|
| | 148 | req.hdf['query.href'] = req.abs_href.query(group=query.group, |
|---|
| | 149 | groupdesc=query.groupdesc and 1 or None, |
|---|
| | 150 | verbose=query.verbose and 1 or None, |
|---|
| | 151 | **query.constraints) |
|---|
| | 152 | return (req.hdf.render('query_rss.cs'), 'application/rss+xml') |
|---|