source: products/quintagroup.referencedatagridfield/trunk/quintagroup/referencedatagridfield/_field.py @ 2279

Last change on this file since 2279 was 2278, checked in by mylan, 14 years ago

Split link_uid on link and uid columns

  • Property svn:eol-style set to native
File size: 5.6 KB
Line 
1#from Products.Archetypes import atapi
2import re
3import logging
4import urlparse
5from urllib import quote
6from types import ListType, TupleType
7
8from AccessControl import ClassSecurityInfo
9
10from Products.CMFCore.utils import getToolByName
11from Products.validation import validation #validators import baseValidators
12from Products.Archetypes.Field import encode, ReferenceField
13from Products.Archetypes.Registry import registerField, registerWidget
14
15from Products.ATReferenceBrowserWidget.ATReferenceBrowserWidget import ReferenceBrowserWidget
16
17from Products.DataGridField.DataGridField import DataGridField
18from Products.DataGridField.DataGridWidget import DataGridWidget
19
20
21# Logger object
22#logger = logging.getLogger('ReferenceDataGridField')
23#logger.debug("ReferenceDataGrid loading")
24
25class ReferenceDataGridWidget(DataGridWidget, ReferenceBrowserWidget):
26    _properties = ReferenceBrowserWidget._properties.copy()
27    _properties.update(DataGridWidget._properties.copy())
28    _properties.update({
29        'macro': "referencedatagridwidget",
30        'column_names': ["Title", "Link", "UID"],
31        'helper_css': ('datagridwidget.css',),
32        'helper_js': ('referencebrowser.js', 'datagridwidget.js',),
33        'force_close_on_insert': True,
34        })
35
36isURL = validation.validatorFor('isURL')
37
38class ReferenceDataGridField(DataGridField, ReferenceField):
39    _properties = ReferenceField._properties.copy()
40    _properties.update(DataGridField._properties.copy())
41    _properties.update({
42        'columns': ('title', 'link', 'uid'),
43        'widget': ReferenceDataGridWidget,
44        'multiValued' : True,
45        })
46
47    security = ClassSecurityInfo()
48
49    security.declarePrivate('isRemoteURL')
50    def isRemoteURL(self, url):
51        return isURL(url) == 1 and True or False
52
53    security.declarePrivate('set')
54    def set(self, instance, value, **kwargs):
55        """
56        The passed in object should be a records object, or a sequence of dictionaries
57        About link data:
58          * interpretations:
59            * if data not starts with standard protocol names (http://, ftp://) than
60              *uid* field data will be used as reference
61          * record removed if:
62            * no data;
63            * data contains UID of not existent object
64        About title:
65          * if there is UID of existent object and record has same title to the original
66            object - title will not be saved.
67        """
68        catalog = getToolByName(instance, "uid_catalog")
69
70        if value is None:
71            value = ()
72
73        if not isinstance(value, (ListType, TupleType)):
74            value = value,
75
76        result = []
77        for row in value:
78            data = {"title":"", "link":"", "uid":""}
79
80            uid = str(row.get("uid", "")).strip()
81            link = str(row.get("link", "")).strip()
82            title = str(row.get('title', "")).strip()
83
84            if not title == "":
85                data["title"] = title
86
87            if link == "":
88                continue
89            elif self.isRemoteURL(link):
90                data["link"] = urlparse.urlunparse(urlparse.urlparse(link))
91            else:
92                if uid == '':
93                    continue
94
95                brains = catalog(UID=uid)
96                if len(brains) == 0:
97                    continue
98                # Found objects with pointed UID
99                brain = brains[0]
100                data["uid"] = uid
101                # Fix title for uid
102                if data['title'] == getattr(brain, "Title", ""):
103                    data['title'] = ""
104            result.append(data)
105
106        DataGridField.set(self, instance, result, **kwargs)
107
108        uids = [r['uid'] for r in result if r['uid']!=""]
109        ReferenceField.set(self, instance, uids, **kwargs)
110       
111    security.declarePrivate('get')
112    def get(self, instance, **kwargs):
113        """ Return DataGridField value
114
115        Value is a list object of rows.
116        Row id dictionary object with standard 'link', 'uid' and 'title' keys
117        plus extra informal *url* and *url_title* keys
118        """
119        purl = getToolByName(instance, "portal_url")
120        # use portal_catalog to hide protected object for the logged in user.
121        catalog = getToolByName(instance, "portal_catalog")
122
123        result = []
124        uids = {}
125        rows = DataGridField.get(self, instance, **kwargs)
126        for row in rows:
127            result.append({
128                # DataGridField row data
129                "uid": row["uid"],
130                "link": row["link"],
131                "title": row["title"],
132                # View data
133                "url": "",
134                "url_title": row["title"]})
135            data = result[-1]
136            # Process remote URL and collect UIDs
137            if row["link"]:
138                data["url"] = quote(row["link"], safe='?$#@/:=+;$,&%')
139                # if title not set for remote url - set it equals to url
140                if not data["url_title"]:
141                    data["url_title"] = row["link"]
142            else:
143                uids[row["uid"]] = data
144        # Process UIDs
145        if uids:
146            brains = catalog(UID=uids.keys())
147            for b in brains:
148                data = uids[b.UID]
149                data["url"] = b.getURL()
150                # If title not set - get it from the brain
151                if not data["url_title"]:
152                    data["url_title"] = self._brains_title_or_id(b, instance)
153
154        return result
155
156
157registerWidget(
158    ReferenceDataGridWidget,
159    title='DataGrid Reference',
160    used_for=('quintagroup.referencedatagridfield.ReferenceDataGridField',)
161    )
162
163registerField(
164    ReferenceDataGridField,
165    title="DataGrid Reference Field",
166    description=("Reference DataGrid field.")
167    )
Note: See TracBrowser for help on using the repository browser.