| 1 | from trac.core import * |
|---|
| 2 | from tractags.api import DefaultTaggingSystem, ITaggingSystemProvider, TagEngine |
|---|
| 3 | from trac.wiki.api import IWikiChangeListener, IWikiSyntaxProvider |
|---|
| 4 | from tractags.expr import Expression |
|---|
| 5 | from trac.util import Markup |
|---|
| 6 | import re |
|---|
| 7 | |
|---|
| 8 | class WikiTaggingSystem(DefaultTaggingSystem): |
|---|
| 9 | """ Subclass of DefaultTaggingSystem that knows how to retrieve wiki page |
|---|
| 10 | titles. """ |
|---|
| 11 | def __init__(self, env): |
|---|
| 12 | DefaultTaggingSystem.__init__(self, env, 'wiki') |
|---|
| 13 | |
|---|
| 14 | def page_info(self, page): |
|---|
| 15 | from trac.wiki import model |
|---|
| 16 | """ Return tuple of (model.WikiPage, title) """ |
|---|
| 17 | page = model.WikiPage(self.env, page) |
|---|
| 18 | |
|---|
| 19 | title = '' |
|---|
| 20 | |
|---|
| 21 | if page.exists: |
|---|
| 22 | text = page.text |
|---|
| 23 | ret = re.search('=\s+([^=]*)=',text) |
|---|
| 24 | title = ret and ret.group(1) or '' |
|---|
| 25 | |
|---|
| 26 | return (page, title) |
|---|
| 27 | |
|---|
| 28 | def name_details(self, name): |
|---|
| 29 | """ Return a tuple of (href, wikilink, title). eg. ("/ticket/1", "#1", "Broken links") """ |
|---|
| 30 | page, title = self.page_info(name) |
|---|
| 31 | href = self.env.href.wiki(name) |
|---|
| 32 | defaults = DefaultTaggingSystem.name_details(self, name) |
|---|
| 33 | return defaults[0:2] + (title,) |
|---|
| 34 | |
|---|
| 35 | class WikiTags(Component): |
|---|
| 36 | """ Implement tags in the Wiki system, a tag:<tag> link resolver and |
|---|
| 37 | correctly deletes tags from Wiki pages that are removed. """ |
|---|
| 38 | |
|---|
| 39 | implements(ITaggingSystemProvider, IWikiChangeListener, IWikiSyntaxProvider) |
|---|
| 40 | |
|---|
| 41 | # ITaggingSystemProvider methods |
|---|
| 42 | def get_tagspaces_provided(self): |
|---|
| 43 | yield 'wiki' |
|---|
| 44 | |
|---|
| 45 | def get_tagging_system(self, tagspace): |
|---|
| 46 | return WikiTaggingSystem(self.env) |
|---|
| 47 | |
|---|
| 48 | # IWikiChangeListener methods |
|---|
| 49 | def wiki_page_added(self, page): |
|---|
| 50 | TagEngine(self.env).flush_link_cache(page) |
|---|
| 51 | |
|---|
| 52 | def wiki_page_changed(self, page, version, t, comment, author, ipnr): |
|---|
| 53 | TagEngine(self.env).flush_link_cache(page) |
|---|
| 54 | |
|---|
| 55 | def wiki_page_deleted(self, page): |
|---|
| 56 | # No point having tags on a non-existent page. |
|---|
| 57 | self.env.log.debug("Removing all tags from 'wiki:%s'" % page.name) |
|---|
| 58 | engine = TagEngine(self.env) |
|---|
| 59 | engine.tagspace.wiki.remove_all_tags(None, page.name) |
|---|
| 60 | engine.flush_link_cache(page) |
|---|
| 61 | |
|---|
| 62 | def wiki_page_version_deleted(self, page): |
|---|
| 63 | # Wiki tags are not versioned. If they were, we'd delete them here. |
|---|
| 64 | TagEngine(self.env).flush_link_cache(page) |
|---|
| 65 | |
|---|
| 66 | # IWikiSyntaxProvider methods |
|---|
| 67 | def get_wiki_syntax(self): |
|---|
| 68 | yield (r'''\[tagged:(?P<tlpexpr>(?:'.*?'|".*?"|\S)+)\s+(?P<tlptitle>.*?]*)\]''', |
|---|
| 69 | lambda f, n, m: self._format_tagged( |
|---|
| 70 | m.group('tlpexpr'), |
|---|
| 71 | m.group('tlptitle'))) |
|---|
| 72 | yield (r'''tagged:(?P<texpr>(?:'.*?'|".*?"|\S)+)''', |
|---|
| 73 | lambda f, n, m: self._format_tagged( |
|---|
| 74 | m.group('texpr'), |
|---|
| 75 | 'tagged:' + m.group('texpr'))) |
|---|
| 76 | |
|---|
| 77 | def get_link_resolvers(self): |
|---|
| 78 | return [] |
|---|
| 79 | |
|---|
| 80 | def _format_tagged(self, target, label): |
|---|
| 81 | if '?' in target: |
|---|
| 82 | target, args = target.split('?')[0:2] |
|---|
| 83 | args = '?' + args |
|---|
| 84 | else: |
|---|
| 85 | args = '' |
|---|
| 86 | href, title = TagEngine(self.env).get_tag_link(target, is_expression=True) |
|---|
| 87 | return Markup('<a href="%s%s" title="%s">%s</a>' % (href, args, |
|---|
| 88 | title, label)) |
|---|
| 89 | |
|---|