|
1 """entity classes for optional library entities |
|
2 |
|
3 :organization: Logilab |
|
4 :copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
|
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
6 """ |
|
7 __docformat__ = "restructuredtext en" |
|
8 |
|
9 from urlparse import urlsplit, urlunsplit |
|
10 from mx.DateTime import now |
|
11 |
|
12 from logilab.common.decorators import cached |
|
13 |
|
14 from cubicweb.common.entity import _marker |
|
15 from cubicweb.entities import AnyEntity, fetch_config |
|
16 |
|
17 def mangle_email(address): |
|
18 try: |
|
19 name, host = address.split('@', 1) |
|
20 except ValueError: |
|
21 return address |
|
22 return '%s at %s' % (name, host.replace('.', ' dot ')) |
|
23 |
|
24 class EmailAddress(AnyEntity): |
|
25 id = 'EmailAddress' |
|
26 fetch_attrs, fetch_order = fetch_config(['address', 'alias', 'canonical']) |
|
27 |
|
28 widgets = { |
|
29 'address' : "EmailWidget", |
|
30 } |
|
31 |
|
32 def dc_title(self): |
|
33 if self.alias: |
|
34 return '%s <%s>' % (self.alias, self.display_address()) |
|
35 return self.display_address() |
|
36 |
|
37 @property |
|
38 def email_of(self): |
|
39 return self.reverse_use_email and self.reverse_use_email[0] |
|
40 |
|
41 @cached |
|
42 def canonical_form(self): |
|
43 if self.canonical: |
|
44 return self |
|
45 rql = 'EmailAddress X WHERE X identical_to Y, X canonical TRUE, Y eid %(y)s' |
|
46 cnrset = self.req.execute(rql, {'y': self.eid}, 'y') |
|
47 if cnrset: |
|
48 return cnrset.get_entity(0, 0) |
|
49 return None |
|
50 |
|
51 def related_emails(self, skipeids=None): |
|
52 # XXX move to eemail |
|
53 # check email relations are in the schema first |
|
54 subjrels = self.e_schema.object_relations() |
|
55 if not ('sender' in subjrels and 'recipients' in subjrels): |
|
56 return |
|
57 rql = 'DISTINCT Any X, S, D ORDERBY D DESC WHERE X sender Y or X recipients Y, X subject S, X date D, Y eid %(y)s' |
|
58 rset = self.req.execute(rql, {'y': self.eid}, 'y') |
|
59 if skipeids is None: |
|
60 skipeids = set() |
|
61 for i in xrange(len(rset)): |
|
62 eid = rset[i][0] |
|
63 if eid in skipeids: |
|
64 continue |
|
65 skipeids.add(eid) |
|
66 yield rset.get_entity(i, 0) |
|
67 |
|
68 def display_address(self): |
|
69 if self.vreg.config['mangle-emails']: |
|
70 return mangle_email(self.address) |
|
71 return self.address |
|
72 |
|
73 def printable_value(self, attr, value=_marker, attrtype=None, |
|
74 format='text/html'): |
|
75 """overriden to return displayable address when necessary""" |
|
76 if attr == 'address': |
|
77 return self.display_address() |
|
78 return super(EmailAddress, self).printable_value(attr, value, attrtype, format) |
|
79 |
|
80 def after_deletion_path(self): |
|
81 """return (path, parameters) which should be used as redirect |
|
82 information when this entity is being deleted |
|
83 """ |
|
84 if self.email_of: |
|
85 return self.email_of.rest_path(), {} |
|
86 return super(EmailAddress, self).after_deletion_path() |
|
87 |
|
88 |
|
89 from logilab.common.deprecation import class_renamed |
|
90 Emailaddress = class_renamed('Emailaddress', EmailAddress) |
|
91 Emailaddress.id = 'Emailaddress' |
|
92 |
|
93 |
|
94 class EProperty(AnyEntity): |
|
95 id = 'EProperty' |
|
96 |
|
97 fetch_attrs, fetch_order = fetch_config(['pkey', 'value']) |
|
98 |
|
99 widgets = { |
|
100 'pkey' : "PropertyKeyWidget", |
|
101 'value' : "PropertyValueWidget", |
|
102 } |
|
103 |
|
104 rest_attr = 'pkey' |
|
105 |
|
106 def typed_value(self): |
|
107 return self.vreg.typed_value(self.pkey, self.value) |
|
108 |
|
109 def dc_description(self): |
|
110 return self.req._(self.vreg.property_info(self.pkey)['help']) |
|
111 |
|
112 def after_deletion_path(self): |
|
113 """return (path, parameters) which should be used as redirect |
|
114 information when this entity is being deleted |
|
115 """ |
|
116 return 'view', {} |
|
117 |
|
118 |
|
119 class Bookmark(AnyEntity): |
|
120 """customized class for Bookmark entities""" |
|
121 id = 'Bookmark' |
|
122 fetch_attrs, fetch_order = fetch_config(['title', 'path']) |
|
123 widgets = { |
|
124 'path' : "StringWidget", |
|
125 } |
|
126 __rtags__ = {'path': 'primary'} |
|
127 |
|
128 def actual_url(self): |
|
129 url = self.req.build_url(self.path) |
|
130 if self.title: |
|
131 urlparts = list(urlsplit(url)) |
|
132 if urlparts[3]: |
|
133 urlparts[3] += '&vtitle=%s' % self.req.url_quote(self.title) |
|
134 else: |
|
135 urlparts[3] = 'vtitle=%s' % self.req.url_quote(self.title) |
|
136 url = urlunsplit(urlparts) |
|
137 return url |
|
138 |
|
139 def action_url(self): |
|
140 return self.absolute_url() + '/follow' |
|
141 |
|
142 |
|
143 class Card(AnyEntity): |
|
144 """customized class for Card entities""" |
|
145 id = 'Card' |
|
146 rest_attr = 'wikiid' |
|
147 |
|
148 fetch_attrs, fetch_order = fetch_config(['title']) |
|
149 |
|
150 def dc_title(self): |
|
151 return self.title |
|
152 |
|
153 def dc_description(self, format='text/plain'): |
|
154 return self.synopsis or u'' |
|
155 |
|
156 class ECache(AnyEntity): |
|
157 """Cache""" |
|
158 id = 'ECache' |
|
159 |
|
160 fetch_attrs, fetch_order = fetch_config(['name']) |
|
161 |
|
162 def touch(self): |
|
163 self.req.execute('SET X timestamp %(t)s WHERE X eid %(x)s', {'t': now(), 'x': self.eid}, 'x') |
|
164 |
|
165 def valid(self, date): |
|
166 return date < self.timestamp |