| 1 | # -*- coding: utf-8 -*- |
|---|
| 2 | """ |
|---|
| 3 | tracattachmentnum: |
|---|
| 4 | a plugin for Trac |
|---|
| 5 | http://trac.edgewall.org |
|---|
| 6 | """ |
|---|
| 7 | |
|---|
| 8 | from trac.core import Component, TracError, implements |
|---|
| 9 | from trac.wiki.api import IWikiMacroProvider |
|---|
| 10 | from trac.wiki.formatter import format_to_oneliner |
|---|
| 11 | from trac.wiki.macros import parse_args |
|---|
| 12 | from trac.config import Option, BoolOption |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | class AttachmentNumMacro(Component): |
|---|
| 16 | """ |
|---|
| 17 | Macro which allows to link to wiki attachment by number instead by name. |
|---|
| 18 | |
|---|
| 19 | Website: http://trac-hacks.org/wiki/AttachmentNumMacro |
|---|
| 20 | |
|---|
| 21 | `$Id: attachmentnum.py 17134 2018-04-16 19:39:49Z rjollos $` |
|---|
| 22 | |
|---|
| 23 | Examples: |
|---|
| 24 | {{{ |
|---|
| 25 | [[AttachmentNum(1)]] # First attachment, result: "attachment:'first.doc'". |
|---|
| 26 | [[AttachmentNum(1,raw=True)]] # First attachment (raw link), result: "raw-attachment:'first.doc'". |
|---|
| 27 | [[AttachmentNum(1,format=short)]] # First attachment, hyper-linked filename is printed only, result: "first.doc". |
|---|
| 28 | }}} |
|---|
| 29 | """ |
|---|
| 30 | implements(IWikiMacroProvider) |
|---|
| 31 | |
|---|
| 32 | raw = BoolOption('attachmentnum', 'raw', False, |
|---|
| 33 | 'Default value for argument `raw`') |
|---|
| 34 | |
|---|
| 35 | format = Option('attachmentnum', 'format', None, |
|---|
| 36 | 'Default value for argument `format`') |
|---|
| 37 | |
|---|
| 38 | # methods for IWikiMacroProvider |
|---|
| 39 | def get_macros(self): |
|---|
| 40 | yield 'AttachmentNum' |
|---|
| 41 | |
|---|
| 42 | def get_macro_description(self, name): |
|---|
| 43 | return self.__doc__ |
|---|
| 44 | |
|---|
| 45 | def expand_macro(self, formatter, name, content): |
|---|
| 46 | largs, kwargs = parse_args(content) |
|---|
| 47 | try: |
|---|
| 48 | num = int(largs[0]) - 1 |
|---|
| 49 | if num < 0: |
|---|
| 50 | raise Exception |
|---|
| 51 | except: |
|---|
| 52 | raise TracError("Argument must be a positive integer!") |
|---|
| 53 | |
|---|
| 54 | if 'raw' in kwargs: |
|---|
| 55 | vraw = kwargs['raw'].lower() |
|---|
| 56 | if vraw in ('yes', 'true', '1', 'on'): |
|---|
| 57 | raw = True |
|---|
| 58 | elif vraw in ('no', 'false', '0', 'off'): |
|---|
| 59 | raw = False |
|---|
| 60 | else: |
|---|
| 61 | raw = self.raw |
|---|
| 62 | |
|---|
| 63 | res = formatter.resource |
|---|
| 64 | id = res.id |
|---|
| 65 | type = res.realm |
|---|
| 66 | |
|---|
| 67 | db = self.env.get_db_cnx() |
|---|
| 68 | cursor = db.cursor() |
|---|
| 69 | cursor.execute("SELECT filename FROM attachment WHERE type=%s " |
|---|
| 70 | "AND id=%s ORDER BY time", (type, id)) |
|---|
| 71 | |
|---|
| 72 | attmnts = cursor.fetchall() |
|---|
| 73 | if len(attmnts) < num + 1 or not attmnts[num] or not attmnts[num][0]: |
|---|
| 74 | raise TracError("Attachment #%i doesn't exists!" % (num + 1)) |
|---|
| 75 | filename = attmnts[num][0] |
|---|
| 76 | |
|---|
| 77 | wikilink = "attachment:'" + filename + "'" |
|---|
| 78 | if raw: |
|---|
| 79 | wikilink = "raw-" + wikilink |
|---|
| 80 | if kwargs.get('format', self.format) == 'short': |
|---|
| 81 | wikilink = "[%s %s]" % (wikilink, filename) |
|---|
| 82 | return format_to_oneliner(self.env, formatter.context, wikilink) |
|---|