Changeset 3065

Show
Ignore:
Timestamp:
01/15/08 20:34:48 (8 months ago)
Author:
ixokai
Message:

Cleaned it up, in general; also added the ability to configure what resources you want to be bread-crumb-trackable.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • breadcrumbsnavplugin/0.11/breadcrumbsnavplugin/breadcrumbs.py

    r3050 r3065  
    1 from trac.core import Component, implements 
    2 from trac.config import Option, IntOption 
     1from trac.core import Component, implements, TracError 
     2from trac.config import Option, IntOption, ListOption 
    33from trac.web import IRequestFilter 
    44from trac.wiki import parse_args 
     
    88from genshi.builder import tag 
    99from genshi.filters.transform import Transformer 
    10 import re 
     10import re, cPickle 
     11from trac.env import IEnvironmentSetupParticipant 
    1112 
    1213class BreadCrumbsSystem(Component): 
    13     implements(IRequestFilter, ITemplateProvider, ITemplateStreamFilter
     14    implements(IRequestFilter, ITemplateProvider, ITemplateStreamFilter, IEnvironmentSetupParticipant
    1415     
    1516    ignore_pattern = Option('breadcrumbs', 'ignore pattern', None,  
     
    1718        the breadcrumbs trail.""") 
    1819     
    19     max_crumbs = IntOption('breadcrumbs', 'max crumbs', 6,  
     20    max_crumbs = IntOption('breadcrumbs', 'max_crumbs', 6,  
    2021        doc="""Indicates the maximum number of breadcrumbs to store per user.""") 
    2122     
     23    supported_paths = ListOption('breadcrumbs', 'paths', '/wiki*,/ticket*,/milestone*', 
     24        doc='List of URL paths to allow breadcrumb tracking. Globs are supported.') 
     25     
    2226    compiled_ignore_pattern = None 
     27     
     28    ## IEnvironmentSetupParticipant 
     29    def environment_created(self): 
     30        self._upgrade_db(self.env.get_db_cnx()) 
     31 
     32    def environment_needs_upgrade(self, db): 
     33        cursor = db.cursor() 
     34 
     35        try: 
     36            cursor.execute( 
     37                "SELECT count(*) FROM session_attribute WHERE name = %s",  
     38                ("breadcrumbs list",) 
     39            ) 
     40            result = cursor.fetchone() 
     41            if int(result[0]): 
     42                return True 
     43                 
     44            return False 
     45        except: 
     46            db.rollback() 
     47            return True 
     48 
     49    def upgrade_environment(self, db): 
     50        self._upgrade_db(db) 
     51 
     52    def _upgrade_db(self, db): 
     53        try: 
     54            from trac.db import DatabaseManager 
     55            db_backend, _ = DatabaseManager(self.env)._get_connector()             
     56 
     57            cursor = db.cursor() 
     58            cursor.execute("DELETE FROM session_attribute WHERE name = %s", ("breadcrumbs list",)) 
     59 
     60        except Exception, e: 
     61            db.rollback() 
     62            self.log.error(e, exc_info=True) 
     63            raise TracError(str(e)) 
     64     
    2365     
    2466    ## IRequestFilter 
     
    2769        return handler 
    2870         
    29     def _get_crumbs(self, req): 
    30         sess = req.session 
    31  
     71    def _get_crumbs(self, sess): 
    3272        crumbs = [] 
    33         if 'breadcrumbs list' in sess: 
    34             raw = sess['breadcrumbs list'] 
     73        if 'breadcrumbs_list' in sess: 
     74            raw = sess['breadcrumbs_list'] 
    3575            try: 
    36                 crumbs = [x.replace('@COMMA@', ',') for x in raw.split(',')] 
     76                crumbs = cPickle.loads(raw.encode('ascii', 'ignore')) 
    3777            except: 
    38                 pass 
     78                del sess['breadcrumbs_list'] 
    3979         
    4080        return crumbs 
     
    4383        if self.compiled_ignore_pattern is None and self.ignore_pattern: 
    4484            self.compiled_ignore_pattern = re.compile(self.ignore_pattern) 
     85         
     86        path = req.path_info 
     87        try: 
     88            if path.count('/') >= 2: 
     89                _, realm, resource = path.split('/', 2) 
    4590             
    46         try: 
    47             path = req.path_info 
    48             if path.count('/') >= 2: 
    49                 _, realm, rest = path.split('/', 2) 
     91                supported = False 
     92             
     93                for pattern in self.supported_paths: 
     94                    if re.match(pattern, path): 
     95                        supported = True 
     96                        break 
    5097                 
    51                 if realm in ('wiki', 'ticket', 'milestone'):             
    52                     if '#' in rest: 
    53                         name = rest[0:rest.index('#')] 
    54                     else: 
    55                         name = rest 
     98                if not supported or (self.compiled_ignore_pattern and 
     99                            self.compiled_ignore_pattern.match(resource)): 
     100                    return template, data, content_type 
     101                 
     102                if '&' in resource: 
     103                    resource = resource[0:resource.index('&')] 
     104                 
     105                sess = req.session 
     106                crumbs = self._get_crumbs(sess) 
     107                 
     108                current = '/'.join( (realm, resource) ) 
     109                if current in crumbs: 
     110                    crumbs.remove(current) 
     111                    crumbs.insert(0, current) 
     112                else: 
     113                    crumbs.insert(0, current) 
     114                    crumbs = crumbs[0:self.max_crumbs] 
    56115                     
    57                     if '&' in name: 
    58                         name = name[0:name.index('&')] 
    59                      
    60                     id = name 
    61                     if realm == "ticket": 
    62                         name = "#" + name 
    63                       
    64                     if self.compiled_ignore_pattern and self.compiled_ignore_pattern.match(id): 
    65                         return template, data, content_type 
    66                      
    67                     sess = req.session 
    68                      
    69                     crumbs = self._get_crumbs(req) 
    70                      
    71                     current = "%s:%s" % (name, req.href("%s/%s" % (realm, id))) 
    72                     if current not in crumbs: 
    73                         crumbs.insert(0, current) 
    74                         crumbs = crumbs[0:self.max_crumbs] 
    75                     else: 
    76                         crumbs.remove(current) 
    77                         crumbs.insert(0, current) 
    78  
    79                     sess['breadcrumbs list'] = ','.join( 
    80                         x.replace(',', '@COMMA@') for x in crumbs 
    81                     ) 
     116                sess['breadcrumbs_list'] = cPickle.dumps(crumbs) 
    82117        except: 
    83118            self.log.exception("Breadcrumb failed :(") 
    84119         
    85  
     120         
    86121        return template, data, content_type 
    87122     
     
    98133     
    99134    def filter_stream(self, req, method, filename, stream, data): 
    100         crumbs = self._get_crumbs(req
     135        crumbs = self._get_crumbs(req.session
    101136        if not crumbs: 
    102137            return stream 
     
    108143         
    109144        for crumb in crumbs: 
    110             title, link = crumb.split(':', 1) 
     145            realm, resource = crumb.split('/', 1) 
     146            name = resource.replace('_', ' ') 
     147 
     148            if realm == "ticket": 
     149                name = "#" + resource 
     150            elif realm != "wiki": 
     151                name = "%s:%s" % (realm, name) 
     152 
     153            link = req.href(realm, resource) 
     154             
    111155            li.append( 
    112156                tag.li( 
    113                     tag.a(title=title, href=link, 
    114                     )(title) 
     157                    tag.a(title=name, href=link, 
     158                    )(name) 
    115159                ) 
    116160            )