Changeset 2801

Show
Ignore:
Timestamp:
11/19/07 19:21:05 (1 year ago)
Author:
osimons
Message:

TocMacro: Various improvements + support for latest 0.11dev with context refactoring + fine-grained permissions.

For details see #1784 - some highlights:

  • Wildcard support on page names
  • titleindex for no pages will return all pages
  • and, see ticket for more...
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • tocmacro/0.11/tractoc/macro.py

    r1955 r2801  
    77 
    88from trac.core import * 
     9from trac.resource import get_resource_url 
     10from trac.util.compat import sorted 
    911from trac.wiki.formatter import OutlineFormatter, system_message 
    1012from trac.wiki.api import WikiSystem, parse_args 
    11 from trac.wiki.macros import WikiMacroBase  
     13from trac.wiki.macros import WikiMacroBase 
     14from trac.wiki.model import WikiPage 
    1215 
    1316 
     
    1821 
    1922 
    20 def outline_tree(ol, outline, context, active, min_depth, max_depth): 
     23def outline_tree(env, ol, outline, context, active, min_depth, max_depth): 
    2124    if min_depth > max_depth: 
    2225        min_depth, max_depth = max_depth, min_depth 
     
    4043                li.append(new_ol) 
    4144                stack[d+1] = (None, new_ol) 
    42             href = context.resource_href(
     45            href = get_resource_url(env, context.resource, context.href
    4346            if href.endswith(context.req.path_info): 
    4447                href = '' 
     
    6972          TracTimeline, TracRss, TracNotification)]] 
    7073    }}} 
     74    A wildcard '*' can be used to fetch a sorted list of all pages starting with 
     75    the preceding pagename stub: 
     76    {{{ 
     77    [[TOC(Trac*, WikiFormatting, WikiMacros)]] 
     78    }}} 
    7179    The following ''control'' arguments change the default behaviour of 
    7280    the TOC macro:  
     
    7785    || {{{inline}}}      || Display TOC inline rather than as a side-bar. || 
    7886    || {{{titleindex}}}  || Only display the page name and title of each page, similar to TitleIndex. || 
    79      
    80     Note that the current page must also be specified if individual wiki 
    81     pages are given in the argument list. 
     87    || {{{notitle}}}     || Supress display of page title. || 
     88    For 'titleindex' argument, an empty pagelist will evaluate to all pages: 
     89    {{{ 
     90    [[TOC(titleindex, notitle, heading=All pages)]] 
     91    }}} 
    8292    """ 
    8393     
    8494    def expand_macro(self, formatter, name, args): 
    8595        self.formatter = formatter 
    86         context = formatter.context 
     96        self.context = formatter.context 
     97        self.resource = formatter.context.resource 
    8798         
    8899        # Bail out if we are in a no-float zone 
     
    91102            return '' 
    92103         
    93         current_page = context.id 
     104        current_page = self.resource.id 
    94105          
    95106        # Split the args 
     
    98109        inline = False 
    99110        pagenames = [] 
    100         heading = kw.pop('heading', 'Table of Contents') 
    101111         
     112        default_heading = 'Table of Contents' 
    102113        params = {'min_depth': 1, 'max_depth': 6} 
    103114        # Global options 
     
    107118                inline = True 
    108119            elif arg == 'noheading': 
    109                 heading = '' 
     120                default_heading = '' 
    110121            elif arg == 'notitle': 
    111122                params['min_depth'] = 2     # Skip page title 
    112123            elif arg == 'titleindex': 
    113124                params['title_index'] = True 
    114                 heading = '
     125                default_heading = default_heading and 'Page Index
    115126            elif arg == 'nofloat': 
    116127                return '' 
    117128            elif arg != '': 
    118129                pagenames.append(arg) 
     130        heading = kw.pop('heading', '') or default_heading 
    119131 
    120132        if 'depth' in kw: 
     
    122134 
    123135        # Has the user supplied a list of pages? 
    124         if not pagenames and 'title_index' not in params: 
    125             pagenames.append(current_page) 
    126             params['root'] = '' 
    127             params['min_depth'] = 2     # Skip page title 
    128  
    129         base = tag.div(class_=not inline and 'wiki-toc' or '') 
     136        if not pagenames: 
     137            if 'title_index' in params: 
     138                pagenames.append('*')       # A marker for 'all' 
     139            else: 
     140                pagenames.append(current_page) 
     141                params['root'] = '' 
     142                params['min_depth'] = 2     # Skip page title 
     143        # Check for wildcards and expand lists 
     144        temp_pagenames = [] 
     145        for pagename in pagenames: 
     146            if pagename.endswith('*'): 
     147                temp_pagenames.extend(sorted( 
     148                        WikiSystem(self.env).get_pages(pagename[:-1]))) 
     149            else: 
     150                temp_pagenames.append(pagename) 
     151        pagenames = temp_pagenames 
     152 
     153        base = tag.div(class_=inline and 'wiki-toc-inline' or 'wiki-toc') 
    130154        ol = tag.ol() 
    131155        base.append([heading and tag.h4(heading), ol]) 
    132156 
    133157        active = len(pagenames) > 1 
    134         if pagenames: 
    135             for pagename in pagenames: 
    136                 if 'title_index' in params
    137                     prefix = pagename.split('/')[0] 
    138                     prefix = prefix.replace("'", "''") # FIXME: what's this? 
    139                     self._render_title_index(ol, prefix, active and \ 
    140                                              pagename.startswith(current_page)) 
    141                 else: 
    142                     self._render_page_outline(ol, pagename, active, params
    143         else: 
    144             self._render_title_index(ol, '', False
     158        for pagename in pagenames: 
     159            page_resource = self.resource(id=pagename) 
     160            if not 'WIKI_VIEW' in self.context.perm(page_resource)
     161                # Not access to the page, so should not be included 
     162                continue 
     163            if 'title_index' in params: 
     164                self._render_title_index(ol, page_resource, active and \ 
     165                            pagename == current_page, 
     166                            params['min_depth'] < 2
     167            else: 
     168                self._render_page_outline(ol, page_resource, active, params
    145169        return base 
    146170 
    147     def get_page_text(self, pagename): 
    148         """Return a tuple of `(text, exists)` for the given `pagename`.""" 
    149         if pagename == self.formatter.context.id: 
     171    def get_page_text(self, page_resource): 
     172        """Return a tuple of `(text, exists)` for the given page (resource).""" 
     173        if page_resource.id == self.resource.id: 
    150174            return (self.formatter.source, True) 
    151175        else: 
    152             # TODO: after sandbox/security merge 
    153             # page = context(id=pagename).resource 
    154             from trac.wiki.model import WikiPage 
    155             page = WikiPage(self.env, pagename, db=self.formatter.db) 
     176            page = WikiPage(self.env, page_resource) 
    156177            return (page.text, page.exists) 
    157178 
    158     def _render_title_index(self, ol, prefix, active): 
    159         all_pages = list(WikiSystem(self.env).get_pages(prefix)) 
    160         if all_pages: 
    161             all_pages.sort() 
    162             for page in all_pages: 
    163                 ctx = self.formatter.context('wiki', page) 
    164                 fmt = OutlineFormatter(ctx) 
    165                 page_text, _ = self.get_page_text(page) # ctx.resource.text 
    166                 fmt.format(page_text, NullOut()) 
    167                 title = '' 
    168                 if fmt.outline: 
    169                     title = ': ' + fmt.outline[0][2] 
    170                 ol.append((tag.li(tag.a(page, href=ctx.resource_href()), 
    171                                   Markup(title), 
    172                                   class_= active and 'active' or None))) 
    173         else: 
     179    def _render_title_index(self, ol, page_resource, active, show_title): 
     180        page_text, page_exists = self.get_page_text(page_resource) 
     181        if not page_exists: 
    174182            ol.append(system_message('Error: No page matching %s found' % 
    175                                      prefix)) 
    176  
    177     def _render_page_outline(self, ol, pagename, active, params): 
    178         page = params.get('root', '') + pagename 
    179         page_text, page_exists = self.get_page_text(page) 
     183                                     page_resource.id)) 
     184            return 
     185        ctx = self.context(page_resource) 
     186        fmt = OutlineFormatter(self.env, ctx) 
     187        fmt.format(page_text, NullOut()) 
     188        title = '' 
     189        if show_title and fmt.outline: 
     190            title = ': ' + fmt.outline[0][2] 
     191        ol.append((tag.li(tag.a(page_resource.id, 
     192                      href=get_resource_url(self.env, page_resource, ctx.href)), 
     193                      Markup(title), 
     194                      class_= active and 'active' or None))) 
     195 
     196    def _render_page_outline(self, ol, page_resource, active, params): 
     197        page = params.get('root', '') + page_resource.id 
     198        page_text, page_exists = self.get_page_text(page_resource) 
    180199        if page_exists: 
    181             ctx = self.formatter.context('wiki', page) 
    182             fmt = OutlineFormatter(ctx) 
     200            ctx = self.context(page_resource) 
     201            fmt = OutlineFormatter(self.env, ctx) 
    183202            fmt.format(page_text, NullOut()) 
    184             outline_tree(ol, fmt.outline, ctx, 
    185                          active and page == self.formatter.context.id, 
     203            outline_tree(self.env, ol, fmt.outline, ctx, 
     204                         active and page_resource.id == self.resource.id, 
    186205                         params['min_depth'], params['max_depth']) 
    187206        else: