source: timingandestimationplugin/branches/trac0.11-Permissions/timingandestimationplugin/blackmagic.py

Last change on this file was 10266, checked in by Russ Tyndall, 12 years ago

fixed UTF-8 field label bugs related to genshi Stream.render calls re #8866

File size: 8.4 KB
RevLine 
[4260]1from trac.core import Component, implements, TracError
2from trac.config import Option, IntOption, ListOption, BoolOption
3from trac.web.chrome import ITemplateProvider, add_stylesheet, add_script
4from pkg_resources import resource_filename
5from trac.web.api import ITemplateStreamFilter
6from genshi.builder import tag
7from genshi.core import Markup, Stream
8from genshi.filters.transform import Transformer
9import re, cPickle
10from trac.perm import IPermissionRequestor
11
[10266]12def textOf(self, **keys):
13    return self.render('text', None, **keys)
14
15Stream.textOf = textOf
16
[4260]17#@staticmethod
18def disable_field(stream, field):
[7919]19    def select_helper(stream):
20        s = Stream(stream)
[10266]21        name = s.select('@name').textOf()
[7919]22        opt = s.select('//option[@selected]')
23        if not opt: s.select('//option[position()=1]')
[10266]24        text = opt.select("text()").textOf()
25        value = s.select('@value').textOf()
[7919]26        if not value: value = text
27
28        for kind,data,pos in tag.span(text, id=("field-%s"%field)).generate():
29            yield kind,data,pos
30        for kind,data,pos in tag.input(value=value, name=name, type="hidden").generate():
31            yield kind,data,pos
32
33
[4260]34    def helper(field_stream):
[4270]35        s = Stream(field_stream)
[10266]36        value = s.select('@value').textOf()
37        name = s.select('@name').textOf()
[4260]38        for kind,data,pos in tag.span(value, id=("field-%s"%field)).generate():
39            yield kind,data,pos
[4270]40        for kind,data,pos in tag.input(value=value, name=name, type="hidden").generate():
41            yield kind,data,pos
[4260]42
[7919]43    stream = stream | Transformer( '//select[@id="field-%s"]' % field ).filter(select_helper)
44    stream = stream | Transformer( '//input[@id="field-%s"]' % field ).filter(helper)
45    return stream
[4260]46
47
48def remove_header(stream, field):
49    """ Removes the display from the ticket properties """
[4261]50    stream = stream | \
51        Transformer('//th[@id="h_%s"]' % field).replace(tag.th(id="h_%s" % field))
52    stream = stream | \
53        Transformer('//td[@headers="h_%s"]' % field).replace(tag.th(id="h_%s" % field))
[4260]54    return stream
55
[4261]56def remove_changelog(stream, field):
57    """ Removes entries from the visible changelog"""
58    def helper(field_stream):
59        s =  Stream(field_stream)
[10266]60        f = s.select('//strong/text()').textOf()
[4261]61        if field != f: #if we are the field just skip it
62            #identity stream filter
63            for kind, data, pos in s:
64                yield kind, data, pos
65    stream = stream | Transformer('//ul[@class="changes"]/li').filter(helper)
66    return stream
67   
68
69def hide_field(stream , field):
70    """ Replaces a field from the form area with an input type=hidden"""
71    def helper (field_stream):
[10266]72        type = Stream(field_stream).select('@type').textOf()
[5348]73        if type == 'checkbox':
[10266]74            if Stream(field_stream).select('@checked').textOf() == "checked":
[5348]75                value = 1
76            else:
77                value = 0
78        else:
[10266]79            value = Stream(field_stream).select('@value').textOf()
80        name = Stream(field_stream).select('@name').textOf()
[4270]81        for kind,data,pos in tag.input( value=value,
[4261]82                                        type="hidden", name=name).generate():
83            yield kind,data,pos
[7919]84
85    def select_helper(stream):
86        s = Stream(stream)
[10266]87        name = s.select('@name').textOf()
[7919]88        opt = s.select('//option[@selected]')
89        if not opt: s.select('//option[position()=1]')
[10266]90        text = opt.select("text()").textOf()
91        value = s.select('@value').textOf()
[7919]92        if not value: value = text
93        for kind,data,pos in tag.input(value=value, name=name, type="hidden").generate():
94            yield kind,data,pos
95
[4261]96    stream = stream | Transformer('//label[@for="field-%s"]' % field).replace(" ")
[7919]97    stream = stream | Transformer('//input[@id="field-%s"]' % field).filter(helper)
98    stream = stream | Transformer('//select[@id="field-%s"]' % field).filter(select_helper)
[4261]99
100    return remove_changelog(remove_header(stream , field), field)
101
[4260]102def remove_field(stream , field):
103    """ Removes a field from the form area"""
104    stream = stream | Transformer('//label[@for="field-%s"]' % field).replace(" ")
[7869]105    stream = stream | Transformer('//*[@id="field-%s"]' % field).replace(" ")
[4261]106    return remove_changelog(remove_header(stream , field), field)
[4260]107
108def istrue(v, otherwise=None):
[7235]109    if isinstance(v, bool):
110        return v
111    if str(v).lower() in ('yes', 'true', '1', 'on'):
[4260]112        return True
[7235]113    if not otherwise:
114        return False
115    return otherwise
[4260]116
[4261]117csection = 'field settings'
118
[4260]119class TicketTweaks(Component):
[4270]120    implements(ITemplateStreamFilter, ITemplateProvider)   
[4260]121    ## ITemplateStreamFilter
122   
123    def filter_stream(self, req, method, filename, stream, data):
[4261]124        self.log.debug('IN BlackMagic')
[4260]125        if not filename == "ticket.html":
[4261]126            self.log.debug('Not a ticket returning')
[4260]127            return stream
[4264]128        fields = self.config.getlist(csection, 'fields', [])
129        self.log.debug('read enchants = %r' % fields)
130        for field in fields:
131            self.log.debug('starting : %s' % field)
[4260]132            disabled = False
133            hidden = False
134            hide_summary = False
[4261]135            remove = False
136            perms = self.config.getlist(csection, '%s.permission' % field, [])
[4264]137            self.log.debug('read permission config: %s has %s' % (field, perms))
[4260]138            for (perm, denial) in [s.split(":") for s in perms] :
139                perm = perm.upper()
[4264]140                self.log.debug('testing permission: %s:%s should act= %s' %
[4261]141                               (field, perm, (not req.perm.has_permission(perm) or perm == "ALWAYS")))
142                if (not req.perm.has_permission(perm) or perm == "ALWAYS"): 
[4260]143                    if denial:
144                        denial = denial.lower()
145                        if denial == "disable":
146                            disabled = True
147                        elif denial == "hide":
148                            hidden = True
[4261]149                        elif denial == "remove":
150                            remove = True
[4260]151                        else:
152                            disabled = True
153                    else:
154                        disabled = True
155                   
[4261]156                if disabled or istrue(self.config.get(csection, '%s.disable' % field, False)):
[4264]157                    self.log.debug('disabling: %s' % field)
[4261]158                    stream = disable_field(stream, field)
[4260]159
[4261]160                if self.config.get(csection, '%s.label' % field, None):
[4264]161                    self.log.debug('labeling: %s' % field)
[4260]162                    stream = stream | Transformer('//label[@for="field-%s"]' % field).replace(
[4261]163                        self.config.get(csection, '%s.label' % field)
[4260]164                    )
165                   
[4261]166                if self.config.get(csection, '%s.notice' % field, None):
[4264]167                    self.log.debug('noticing: %s' % field)
[4260]168                    stream = stream | Transformer('//*[@id="field-%s"]' % field).after(
169                        tag.br() + tag.small()(
170                            tag.em()(
[4261]171                                Markup(self.config.get(csection, '%s.notice' % field))
[4260]172                            )
173                        )
174                    )
175                   
[4261]176                tip = self.config.get(csection, '%s.tip' % field, None)
[4260]177                if tip:
[4264]178                    self.log.debug('tipping: %s' % field)
[4260]179                    stream = stream | Transformer('//div[@id="banner"]').before(
180                        tag.script(type="text/javascript", 
181                        src=req.href.chrome("blackmagic", "js", "wz_tooltip.js"))()
182                    )
183                   
184                    stream = stream | Transformer('//*[@id="field-%s"]' % field).attr(
185                        "onmouseover", "Tip('%s')" % tip.replace(r"'", r"\'")
186                    )
187                   
[4261]188                if remove or istrue(self.config.get(csection, '%s.remove' % field, None)):
[4264]189                    self.log.debug('removing: %s' % field)
[4261]190                    stream = remove_field(stream, field)
191
192                if hidden or istrue(self.config.get(csection, '%s.hide' % field, None)):
[4264]193                    self.log.debug('hiding: %s' % field)
[4261]194                    stream = hide_field(stream, field)
[4260]195                   
196        return stream
197
198    ## ITemplateProvider
199
200    def get_htdocs_dirs(self):
201        from pkg_resources import resource_filename
202        return [('blackmagic', resource_filename(__name__, 'htdocs'))]
203         
204    def get_templates_dirs(self):
205        return []   
Note: See TracBrowser for help on using the repository browser.