Edgewall Software

Changes between Version 13 and Version 14 of CookBook/Notification/Subscriptions


Ignore:
Timestamp:
Sep 3, 2018, 10:57:51 PM (6 years ago)
Author:
Peter Suter
Comment:

Added TesterCustomFieldSubscriber

Legend:

Unmodified
Added
Removed
Modified
  • CookBook/Notification/Subscriptions

    v13 v14  
    3223221. Users can manage this subscription in [/prefs/notification their preferences].
    323323
    324 See also: #12728
     324See also: #12728
     325
     326== Subscribe via custom ticket field
     327
     328[TracTicketsCustomFields Custom ticket fields] can be configured to behave like an additional [wiki:TracTickets#/Cc Cc field]. For example a `tester` field can notify employees responsible for testing a feature, separately from other Cc'd users.
     329
     3301. Create a [TracTicketsCustomFields custom ticket fields] `tester`.
     3311. Create a [TracDev/PluginDevelopment#Singlefileplugins single file plugin] that implements [wiki:TracDev/PluginDevelopment/ExtensionPoints/trac.notification.api.INotificationSubscriber INotificationSubscriber]:
     332{{{#!python
     333# -*- coding: utf-8 -*-
     334#
     335# Copyright (C) 2018 Edgewall Software
     336# All rights reserved.
     337#
     338# This software is licensed as described in the file COPYING, which
     339# you should have received as part of this distribution. The terms
     340# are also available at http://trac.edgewall.org/wiki/TracLicense.
     341#
     342# This software consists of voluntary contributions made by many
     343# individuals. For the exact contribution history, see the revision
     344# history and logs, available at http://trac.edgewall.org/log/.
     345
     346from trac.core import Component, implements
     347from trac.notification.api import INotificationSubscriber, NotificationSystem
     348from trac.notification.mail import RecipientMatcher
     349from trac.notification.model import Subscription
     350from trac.web.chrome import Chrome
     351
     352class TesterCustomFieldSubscriber(Component):
     353    """Subscriber for custom ticket field."""
     354
     355    implements(INotificationSubscriber)
     356   
     357    field_name = 'tester'
     358
     359    # INotificationSubscriber methods
     360
     361    def matches(self, event):
     362        if event.realm != 'ticket':
     363            return
     364        if event.category not in ('created', 'changed', 'attachment added',
     365                                  'attachment deleted'):
     366            return
     367
     368        # Custom field with comma-separated string. Parse to set.
     369        chrome = Chrome(self.env)
     370        to_set = lambda field: set(chrome.cc_list(field))
     371        user_set = to_set(event.target[self.field_name] or '')
     372
     373        # Harvest previous field values
     374        if 'fields' in event.changes and self.field_name in event.changes['fields']:
     375            field_set.update(to_set(event.changes['fields'][self.field_name]['old']))
     376
     377        matcher = RecipientMatcher(self.env)
     378        klass = self.__class__.__name__
     379        sids = set()
     380        for field in field_set:
     381            recipient = matcher.match_recipient(field)
     382            if not recipient:
     383                continue
     384            sid, auth, addr = recipient
     385
     386            # Default subscription
     387            for s in self.default_subscriptions():
     388                yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4]
     389            if sid:
     390                sids.add((sid, auth))
     391
     392        for s in Subscription.find_by_sids_and_class(self.env, sids, klass):
     393            yield s.subscription_tuple()
     394
     395    def description(self):
     396        return "Ticket that I'm listed in as %s is modified" % self.field_name
     397
     398    def default_subscriptions(self):
     399        klass = self.__class__.__name__
     400        return NotificationSystem(self.env).default_subscriptions(klass)
     401
     402    def requires_authentication(self):
     403        return True
     404}}}
     4051. Users can manage this subscription in [/prefs/notification their preferences].