source: products/quintagroup.analytics/trunk/quintagroup/analytics/browser/views.py @ 3170

Last change on this file since 3170 was 3170, checked in by zidane, 13 years ago

fix pyflakes

  • Property svn:eol-style set to native
File size: 19.4 KB
Line 
1from Acquisition import aq_base
2from zope.component import getUtility, getMultiAdapter, queryMultiAdapter
3
4from OFS.interfaces import IPropertyManager
5from Products.Five.browser import BrowserView
6from Products.CMFCore.utils import getToolByName
7from Products.CMFCore.interfaces import IFolderish
8from Products.Archetypes.interfaces import IBaseFolder
9from plone.portlets.interfaces import IPortletManager
10from plone.portlets.interfaces import IPortletAssignmentMapping
11from plone.portlets.interfaces import ILocalPortletAssignmentManager
12try:
13    from plone.portlets.interfaces import IPortletAssignmentSettings
14    IPortletAssignmentSettings
15except ImportError:
16    "Before plon4 we don't have an annotation storage for settings."
17    IPortletAssignmentSettings = lambda assignment: {}
18
19from GChartWrapper import VerticalBarStack
20
21from quintagroup.analytics.config import COLORS, OTHER_TYPES, NO_WF_BIND
22
23
24class OwnershipByType(BrowserView):
25    MAX = 10
26
27    def __init__(self, context, request):
28        self.context = context
29        self.request = request
30        self.cat = getToolByName(self.context, 'portal_catalog')
31        self.users = None
32        self.total = None
33        self.types = None
34        self.data = {}
35
36    def getUsers(self):
37        if self.users is None:
38            index = self.cat._catalog.getIndex('Creator')
39            data = {}
40            for k in index._index.keys():
41                haslen = hasattr(index._index[k], '__len__')
42                if haslen:
43                    data[k] = len(index._index[k])
44                else:
45                    data[k] = 1
46            data = data.items()
47            data.sort(lambda a, b: a[1] - b[1])
48            data.reverse()
49            data = data[:self.MAX]
50            self.users = [i[0] for i in data]
51            self.total = [i[1] for i in data]
52        return self.users
53
54    def getTypes(self, all=False):
55        if self.types is None:
56            index = self.cat._catalog.getIndex('portal_type')
57            data = {}
58            for k in index._index.keys():
59                if not k:
60                    continue
61                haslen = hasattr(index._index[k], '__len__')
62                if haslen:
63                    data[k] = len(index._index[k])
64                else:
65                    data[k] = 1
66            data = data.items()
67            data.sort(lambda a, b: a[1] - b[1])
68            data.reverse()
69            self.types = [i[0] for i in data]
70        return all and self.types or self.types[:self.MAX]
71
72    def getContent(self, type_):
73        if type_ not in self.data:
74            data = self.data[type_] = []
75            for user in self.getUsers():
76                res = self.cat(portal_type=type_, Creator=user)
77                l = len(res)
78                if l == 0:
79                    data.append(0)
80                else:
81                    data.append(l)
82        return self.data[type_]
83
84    def getTotal(self):
85        return self.total
86
87    def getChart(self):
88        data = []
89        types = self.getTypes()
90        for type_ in types:
91            data.append(self.getContent(type_))
92        other = [self.getContent(t) for t in self.getTypes(
93                                                    all=True)[self.MAX:]]
94        if other:
95            data.append([sum(l) for l in zip(*other)])
96        max_value = max(self.getTotal())
97        chart = VerticalBarStack(data, encoding='text')
98        types = other and types + OTHER_TYPES or types
99        chart.title('Content ownership by type').legend(*(types))
100        chart.bar('a', 10, 0).legend_pos("b")
101        chart.color(*COLORS)
102        chart.size(800, 375).scale(0, max_value).axes('xy').label(*self.users)
103        chart.axes.type("y")
104        chart.axes.range(0, 0, max_value)
105        return chart.img()
106
107
108class OwnershipByState(BrowserView):
109    MAX = 10
110
111    def __init__(self, context, request):
112        self.context = context
113        self.request = request
114        self.cat = getToolByName(self.context, 'portal_catalog')
115        self.users = None
116        self.states = None
117        self.total = None
118        self.data = {}
119
120    def getUsers(self):
121        if self.users is None:
122            index = self.cat._catalog.getIndex('Creator')
123            data = {}
124            for k in index._index.keys():
125                haslen = hasattr(index._index[k], '__len__')
126                if haslen:
127                    data[k] = len(index._index[k])
128                else:
129                    data[k] = 1
130            data = data.items()
131            data.sort(lambda a, b: a[1] - b[1])
132            data.reverse()
133            data = data[:self.MAX]
134            self.users = [i[0] for i in data]
135            self.total = [i[1] for i in data]
136        return self.users
137
138    def getStates(self):
139        if self.states is None:
140            index = self.cat._catalog.getIndex('review_state')
141            data = {}
142            for k in index._index.keys():
143                haslen = hasattr(index._index[k], '__len__')
144                if haslen:
145                    data[k] = len(index._index[k])
146                else:
147                    data[k] = 1
148            data = data.items()
149            data.sort(lambda a, b: a[1] - b[1])
150            data.reverse()
151            self.states = [i[0] for i in data]
152        return self.states
153
154    def getContent(self, type_):
155        if type_ not in self.data:
156            if NO_WF_BIND not in self.data:
157                self.data[NO_WF_BIND] = self.getTotal()
158            data = self.data[type_] = []
159            for user in self.getUsers():
160                res = self.cat(review_state=type_, Creator=user)
161                l = len(res)
162                if l == 0:
163                    data.append(0)
164                else:
165                    data.append(l)
166            if len(data) > 0:
167                self.data[NO_WF_BIND] = map(lambda t, d: t - d,
168                                            self.data[NO_WF_BIND], data)
169        return self.data[type_]
170
171    def getNoWFContentTitle(self):
172        return NO_WF_BIND
173
174    def getNoWFContent(self):
175        return self.getContent(NO_WF_BIND)
176
177    def getTotal(self):
178        if self.total is None:
179            self.getUsers()
180        return self.total
181
182    def getChart(self):
183        data = []
184        for state in self.getStates():
185            data.append(self.getContent(state))
186        data.append(self.getNoWFContent())
187        max_value = max(self.getTotal())
188        chart = VerticalBarStack(data, encoding='text')
189        title = 'Content ownership by state'
190        chart.title(title).legend(*self.states + [NO_WF_BIND])
191        chart.bar('a', 10, 0).legend_pos("b")
192        chart.color(*COLORS)
193        chart.size(800, 375).scale(0, max_value).axes('xy').label(*self.users)
194        chart.axes.type("y")
195        chart.axes.range(0, 0, max_value)
196        return chart.img()
197
198
199class TypeByState(BrowserView):
200    MAX = 10
201
202    def __init__(self, context, request):
203        self.context = context
204        self.request = request
205        self.cat = getToolByName(self.context, 'portal_catalog')
206        self.types = None
207        self.states = None
208        self.total = None
209        self.data = {}
210
211    def getTypes(self):
212        if self.types is None:
213            index = self.cat._catalog.getIndex('portal_type')
214            data = {}
215            for k in index._index.keys():
216                if not k:
217                    continue
218                haslen = hasattr(index._index[k], '__len__')
219                if haslen:
220                    data[k] = len(index._index[k])
221                else:
222                    data[k] = 1
223            data = data.items()
224            data.sort(lambda a, b: a[1] - b[1])
225            data.reverse()
226            self.types = [i[0] for i in data[:self.MAX]]
227            self.total = [i[1] for i in data[:self.MAX]]
228        return self.types
229
230    def getStates(self):
231        if self.states is None:
232            index = self.cat._catalog.getIndex('review_state')
233            data = {}
234            for k in index._index.keys():
235                haslen = hasattr(index._index[k], '__len__')
236                if haslen:
237                    data[k] = len(index._index[k])
238                else:
239                    data[k] = 1
240            data = data.items()
241            data.sort(lambda a, b: a[1] - b[1])
242            data.reverse()
243            self.states = [i[0] for i in data]
244        return self.states
245
246    def getContent(self, state):
247        if state not in self.data:
248            if NO_WF_BIND not in self.data:
249                self.data[NO_WF_BIND] = self.getTotal()
250            data = self.data[state] = []
251            for type_ in self.getTypes():
252                res = self.cat(portal_type=type_, review_state=state)
253                l = len(res)
254                if l == 0:
255                    data.append(0)
256                else:
257                    data.append(l)
258            if len(data) > 0:
259                self.data[NO_WF_BIND] = map(lambda t, d: t - d,
260                                            self.data[NO_WF_BIND], data)
261        return self.data[state]
262
263    def getTotal(self):
264        if self.total is None:
265            self.getTypes()
266        return self.total
267
268    def getNoWFContentTitle(self):
269        return NO_WF_BIND
270
271    def getNoWFContent(self):
272        return self.getContent(NO_WF_BIND)
273
274    def getChart(self):
275        data = []
276        for state in self.getStates():
277            data.append(self.getContent(state))
278        data.append(self.getContent(NO_WF_BIND))
279        max_value = max(self.getTotal())
280        chart = VerticalBarStack(data, encoding='text')
281        chart.title('Content type by state').legend(
282            *self.states + [NO_WF_BIND])
283        chart.bar('a', 10, 0).legend_pos("b")
284        chart.color(*COLORS)
285        chart.size(800, 375).scale(0, max_value).axes('xy').label(*self.types)
286        chart.axes.type("y")
287        chart.axes.range(0, 0, max_value)
288        return chart.img()
289
290
291class LegacyPortlets(BrowserView):
292    def __init__(self, context, request):
293        self.context = context
294        self.request = request
295        self.total = None
296        self.DEBUG = False
297        self.expressions = set()
298
299    def _getInfo(self, obj):
300        href = obj.absolute_url()
301        path = '/'.join(obj.getPhysicalPath())
302        info = {
303            'path': path,
304            'href': href,
305            'left_slots': None,
306            'right_slots': None,
307        }
308        if IPropertyManager.providedBy(obj):
309            obj = aq_base(obj)
310            if obj.hasProperty('left_slots'):
311                info['left_slots'] = obj.getProperty('left_slots')
312                self.expressions = self.expressions.union(
313                                            set(info['left_slots']))
314            if obj.hasProperty('right_slots'):
315                info['right_slots'] = obj.getProperty('right_slots')
316                self.expressions = self.expressions.union(
317                                            set(info['right_slots']))
318        return info
319
320    def _walk(self, obj, level=-1):
321        yield self._getInfo(obj)
322        if level != 0 and (IFolderish.providedBy(obj) \
323                       or IBaseFolder.providedBy(obj)):
324            for v in obj.contentValues():
325                for i in self._walk(v, level - 1):
326                    yield i
327
328    def getPortlets(self):
329        level = self.request.form.get('level', 1)
330        try:
331            level = level and int(level) or 1
332        except ValueError:
333            level = 1
334        infos = []
335        for i in self._walk(self.context, level):
336            if self.DEBUG or i['left_slots'] is not None \
337                          or i['right_slots'] is not None:
338                infos.append(i)
339        self.total = len(infos)
340        return infos
341
342    def getTotal(self):
343        return self.total
344
345    def getAllPortletExpressions(self):
346        exprs = []
347        for name in self.expressions:
348            name = name.split('|')[0]
349            if not '/macros/' in name:
350                name = name.split('/')[-1]
351            name = name.strip()
352            if name not in exprs:
353                exprs.append(name)
354        exprs.sort()
355        return exprs
356
357
358class PropertiesStats(BrowserView):
359    def __init__(self, context, request):
360        self.context = context
361        self.request = request
362        self.total = None
363        self.DEBUG = False
364        self.expressions = set()
365        self.proplist = []
366        self.propname = self.request.form.get('propname') or ""
367
368    def _getInfo(self, obj):
369
370        href = obj.absolute_url()
371        path = '/'.join(obj.getPhysicalPath())
372        info = {
373            'path': path,
374            'href': href,
375            'slots': None,
376        }
377        if IPropertyManager.providedBy(obj):
378            obj = aq_base(obj)
379            self.proplist.extend(
380                    [i for i in obj.propertyIds() if i not in self.proplist])
381            if obj.hasProperty(self.propname):
382                info['slots'] = obj.getProperty(self.propname)
383                if isinstance(info['slots'], int):
384                    info['slots'] = str(info['slots'])
385                if not isinstance(info['slots'], basestring):
386                    self.expressions = self.expressions.union(
387                                                set(info['slots']))
388                else:
389                    self.expressions = self.expressions.union(
390                                                set([info['slots']]))
391        return info
392
393    def _walk(self, obj, level=-1):
394        yield self._getInfo(obj)
395        if level != 0 and (IFolderish.providedBy(obj) \
396                       or IBaseFolder.providedBy(obj)):
397            for v in obj.contentValues():
398                for i in self._walk(v, level - 1):
399                    yield i
400
401    def getPropsList(self):
402        level = self.request.form.get('level', 1)
403        try:
404            level = level and int(level) or 1
405        except ValueError:
406            level = 1
407        infos = []
408        for i in self._walk(self.context, level):
409            if self.DEBUG or i['slots'] is not None:
410                infos.append(i)
411        self.total = len(infos)
412        return infos
413
414    def getTotal(self):
415        return self.total
416
417    def getAllPortletExpressions(self):
418        exprs = []
419        for name in self.expressions:
420            name = name.strip()
421            if name not in exprs:
422                exprs.append(name)
423        #exprs.sort()
424        return exprs
425
426
427class PortletsStats(BrowserView):
428    def __init__(self, context, request):
429        self.context = context
430        self.request = request
431        self.total = None
432        self.DEBUG = False
433        self.expressions = set()
434        self.proplist = []
435        self.propname = self.request.form.get('propname') or ""
436
437    def getAssignmentMappingUrl(self, context, manager):
438        baseUrl = str(getMultiAdapter((context, self.request),
439                                      name='absolute_url'))
440        return '%s/++contextportlets++%s' % (baseUrl, manager.__name__)
441
442    def getAssignmentsForManager(self, context, manager):
443        assignments = getMultiAdapter((context, manager),
444                                      IPortletAssignmentMapping)
445        return assignments.values()
446
447    def getPortletsMapping(self, context):
448        leftcolumn = getUtility(IPortletManager, name=u'plone.leftcolumn',
449                                context=context)
450        rightcolumn = getUtility(IPortletManager, name=u'plone.rightcolumn',
451                                 context=context)
452        leftmapping = getMultiAdapter((context, leftcolumn,),
453                                      IPortletAssignmentMapping)
454        rightmapping = getMultiAdapter((context, rightcolumn,),
455                                       IPortletAssignmentMapping)
456        return (leftmapping, rightmapping)
457
458    def getLocalPortletsManager(self, context):
459        leftcolumn = getUtility(IPortletManager, name='plone.leftcolumn',
460                                context=context)
461        rightcolumn = getUtility(IPortletManager, name='plone.rightcolumn',
462                                 context=context)
463        leftmanager = getMultiAdapter((context, leftcolumn,),
464                                      ILocalPortletAssignmentManager)
465        rightmanager = getMultiAdapter((context, rightcolumn,),
466                                       ILocalPortletAssignmentManager)
467        return (leftmanager, rightmanager)
468
469    def getPortletsManager(self, context):
470        left = getUtility(IPortletManager, name='plone.leftcolumn',
471                          context=context)
472        right = getUtility(IPortletManager, name='plone.rightcolumn',
473                           context=context)
474        return (left, right)
475
476    def portlets_for_assignments(self, assignments, manager, base_url):
477        data = []
478        for idx in range(len(assignments)):
479            name = assignments[idx].__name__
480
481            editview = queryMultiAdapter(
482                (assignments[idx], self.request), name='edit', default=None)
483
484            if editview is None:
485                editviewName = ''
486            else:
487                editviewName = '%s/%s/edit' % (base_url, name)
488
489            settings = IPortletAssignmentSettings(assignments[idx])
490
491            data.append({
492                'title': assignments[idx].title,
493                'editview': editviewName,
494                'visible': settings.get('visible', True),
495                })
496        return data
497
498    def getPortlets(self, context, mapping, manager):
499        #import pdb; pdb.set_trace()
500        return mapping.keys()
501
502    def _getInfo(self, obj):
503        href = obj.absolute_url()
504        path = '/'.join(obj.getPhysicalPath())
505        info = {
506            'path': path,
507            'href': href,
508            'left_slots': None,
509            'right_slots': None,
510        }
511        left, right = self.getPortletsManager(obj)
512        #leftmapping, rightmapping = self.getPortletsMapping(obj)
513        #leftmanager, rightmanager = self.getLocalPortletsManager(obj)
514        #info['left_slots'] = self.getPortlets(obj, leftmapping, leftmanager)
515        #info['right_slots'] = self.getPortlets(obj, rightmapping,rightmanager)
516        lass = self.getAssignmentsForManager(obj, left)
517        rass = self.getAssignmentsForManager(obj, right)
518        lurl = self.getAssignmentMappingUrl(obj, left)
519        rurl = self.getAssignmentMappingUrl(obj, right)
520        plass = self.portlets_for_assignments(lass, left, lurl)
521        prass = self.portlets_for_assignments(rass, right, rurl)
522        #print obj, plass, prass
523        info['left_slots'] = plass  # [i['title'] for i in plass]
524        info['right_slots'] = prass  # [i['title'] for i in prass]
525        return info
526
527    def _walk(self, obj, level=-1):
528        try:
529            yield self._getInfo(obj)
530        except:
531            pass
532        if level != 0 and (IFolderish.providedBy(obj) \
533                       or IBaseFolder.providedBy(obj)):
534            for v in obj.contentValues():
535                for i in self._walk(v, level - 1):
536                    yield i
537
538    def getPropsList(self):
539        level = self.request.form.get('level', 1)
540        try:
541            level = level and int(level) or 1
542        except ValueError:
543            level = 1
544        infos = []
545        for i in self._walk(self.context, level):
546            if self.DEBUG or i['left_slots'] is not None \
547                          or i['right_slots'] is not None:
548                infos.append(i)
549        self.total = len(infos)
550        return infos
551
552    def getTotal(self):
553        return self.total
554
555    def getAllPortletExpressions(self):
556        exprs = []
557        for name in self.expressions:
558            name = name.strip()
559            if name not in exprs:
560                exprs.append(name)
561        #exprs.sort()
562        return exprs
Note: See TracBrowser for help on using the repository browser.