source: peerreviewplugin/tags/0.12/3.1/codereview/tracgenericclass/api.py

Last change on this file was 16451, checked in by Ryan J Ollos, 6 years ago

Fix indentation

File size: 6.2 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2010-2015 Roberto Longobardi
4#
5# This file is part of the Test Manager plugin for Trac.
6#
7# This software is licensed as described in the file COPYING, which
8# you should have received as part of this distribution. The terms
9# are also available at:
10#   https://trac-hacks.org/wiki/TestManagerForTracPluginLicense
11#
12# Author: Roberto Longobardi <otrebor.dev@gmail.com>
13#
14
15from trac.search import ISearchSource
16from trac.util import get_reporter_id
17from trac.web.api import IRequestHandler
18from trac.web.chrome import ITemplateProvider
19
20from codereview.tracgenericclass.model import GenericClassModelProvider
21from trac.core import Interface, Component, ExtensionPoint, implements
22from codereview.tracgenericclass.util import get_dictionary_from_string,\
23    formatExceptionInfo
24
25
26class IGenericObjectChangeListener(Interface):
27    """
28    Extension point interface for components that require notification
29    when objects are created, modified, or deleted.
30    """
31
32    def object_created(self, g_object):
33        """Called when an object is created."""
34
35    def object_changed(self, g_object, comment, author, old_values):
36        """Called when an object is modified.
37
38        `old_values` is a dictionary containing the previous values of the
39        fields that have changed.
40        """
41
42    def object_deleted(self, g_object):
43        """Called when an object is deleted."""
44
45
46class GenericClassSystem(Component):
47    """
48    Generic Class system for Trac.
49    """
50
51    implements(IRequestHandler, ITemplateProvider, ISearchSource)
52
53    change_listeners = ExtensionPoint(IGenericObjectChangeListener)
54
55
56    # Change listeners management
57
58    def object_created(self, testobject):
59        for c in self.change_listeners:
60            c.object_created(testobject)
61
62    def object_changed(self, testobject, comment, author):
63        for c in self.change_listeners:
64            c.object_changed(testobject, comment, author, testobject._old)
65
66    def object_deleted(self, testobject):
67        for c in self.change_listeners:
68            c.object_deleted(testobject)
69
70
71    # IRequestHandler methods
72
73    def match_request(self, req):
74        return (req.path_info.startswith('/propertyupdate'))
75
76    def process_request(self, req):
77        """
78        Handles Ajax requests to change an object's property.
79        """
80        author = get_reporter_id(req, 'author')
81
82        if req.path_info.startswith('/propertyupdate'):
83            realm = req.args.get('realm')
84            key_str = req.args.get('key')
85            name = req.args.get('name')
86            value = req.args.get('value')
87
88            result = 'ERROR'
89
90            key = get_dictionary_from_string(key_str)
91
92            try:
93                self.env.log.debug("Setting property %s to %s, in %s with key %s" % (name, value, realm, key))
94
95                gclass_modelprovider = GenericClassModelProvider(self.env)
96
97                gclass_modelprovider.check_permission(req, realm, key_str, name, value)
98
99                obj = gclass_modelprovider.get_object(realm, key)
100
101                # Set the required property
102                obj[name] = value
103
104                obj.author = author
105                obj.remote_addr = req.remote_addr
106                if obj is not None and obj.exists:
107                    comment = "Property changed"
108                    obj.save_changes(author, comment)
109
110                    # Call listeners
111                    self.object_changed(obj, comment, author)
112
113                else:
114                    self.env.log.debug("Object to update not found. Creating it.")
115                    props_str = req.args.get('props')
116                    if props_str is not None and not props_str == '':
117                        # In order to create an object, additional properties may be required
118                        props = get_dictionary_from_string(props_str)
119                        obj.set_values(props)
120                    obj.insert()
121
122                    # Call listeners
123                    self.object_created(obj)
124
125                result = 'OK'
126
127            except:
128                self.env.log.debug(formatExceptionInfo())
129
130            req.send_header("Content-Length", len(result))
131            req.write(result)
132            return
133
134        return 'empty.html', {}, None
135
136
137    # ITemplateProvider methods
138    def get_templates_dirs(self):
139        """
140        Return the absolute path of the directory containing the provided
141        Genshi templates.
142        """
143        from pkg_resources import resource_filename
144        return [resource_filename(__name__, 'templates')]
145
146    def get_htdocs_dirs(self):
147        """
148        Return the absolute path of a directory containing additional
149        static resources (such as images, style sheets, etc).
150        """
151        from pkg_resources import resource_filename
152        return [('tracgenericclass', resource_filename(__name__, 'htdocs'))]
153
154
155    # ISearchSource methods
156
157    def get_search_filters(self, req):
158        gclass_modelprovider = GenericClassModelProvider(self.env)
159
160        for realm in gclass_modelprovider.get_known_realms():
161            try:
162                gclass_modelprovider.get_class_provider(realm).check_permission(req, realm, key_str=None, operation='search')
163
164                metadata = gclass_modelprovider.get_metadata(realm)
165
166                if 'searchable' in metadata and metadata['searchable']:
167                    if 'label' in metadata:
168                        label = metadata['label']
169                    else:
170                        label = realm.capitalize()
171
172                    yield (realm, label)
173
174            except:
175                self.env.log.debug("No permission to search on realm %s." % realm)
176
177
178    def get_search_results(self, req, terms, filters):
179        gclass_modelprovider = GenericClassModelProvider(self.env)
180
181        known_realms = gclass_modelprovider.get_known_realms()
182
183        for realm in filters:
184            if realm in known_realms:
185                metadata = gclass_modelprovider.get_metadata(realm)
186
187                if 'searchable' in metadata and metadata['searchable']:
188                    obj = gclass_modelprovider.get_object(realm)
189                    if obj is not None:
190                        for result in obj.get_search_results(req, terms, filters):
191                            yield result
Note: See TracBrowser for help on using the repository browser.