source: products/quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/comments.py @ 1589

Last change on this file since 1589 was 370, checked in by piv, 18 years ago

changed to geoLocation, Marker functionality

File size: 6.5 KB
Line 
1from xml.dom import minidom
2
3from zope.interface import classProvides, implements
4
5from Acquisition import aq_base
6from Products.CMFCore import utils
7from Products.CMFDefault import DiscussionItem
8from Products.CMFDefault.exceptions import DiscussionNotAllowed
9
10from collective.transmogrifier.interfaces import ISection, ISectionBlueprint
11from collective.transmogrifier.utils import defaultMatcher
12
13class CommentsExporterSection(object):
14    classProvides(ISectionBlueprint)
15    implements(ISection)
16
17    def __init__(self, transmogrifier, name, options, previous):
18        self.previous = previous
19        self.context = transmogrifier.context
20
21        self.pathkey = defaultMatcher(options, 'path-key', name, 'path')
22        self.fileskey = options.get('files-key', '_files').strip()
23
24        self.doc = minidom.Document()
25
26    def __iter__(self):
27        for item in self.previous:
28            pathkey = self.pathkey(*item.keys())[0]
29
30            if not pathkey:
31                yield item; continue
32
33            path = item[pathkey]
34            obj = self.context.unrestrictedTraverse(path, None)
35            if obj is None:         # path doesn't exist
36                yield item; continue
37
38            # check if object has comments
39            discussion_container = getattr(aq_base(obj), 'talkback', None)
40            if discussion_container is not None:
41                data = self.extractComments(discussion_container)
42                if data:
43                    files = item.setdefault(self.fileskey, {})
44                    item[self.fileskey]['comments'] = {
45                        'name': '.comments.xml',
46                        'data': data,
47                    }
48
49            yield item
50
51    def extractComments(self, container):
52        doc = self.doc
53
54        items = container.objectItems()
55        if not items:
56            return None
57
58        root = doc.createElement('discussion')
59        doc.appendChild(root)
60        for item_id, item in items:
61            hdrlist = item.getMetadataHeaders()
62            # get creator (it is displayed in "Posted by")
63            hdrlist.append(('Creator', item.Creator()))
64            # get modification date (also is displayed)
65            hdrlist.append(('Modification_date', item.ModificationDate()))
66            # get relation
67            hdrlist.append(('In_reply_to', str(item.in_reply_to)))
68            # get comment text
69            hdrlist.append(('Text', item.text))
70
71            item_elem = doc.createElement('item')
72            attr = doc.createAttribute('id')
73            attr.value = item_id
74            item_elem.setAttributeNode(attr)
75
76            for k, v in hdrlist:
77                field = doc.createElement('field')
78                attr = doc.createAttribute('name')
79                attr.value = k
80                field.setAttributeNode(attr)
81                text = doc.createTextNode(v)
82                field.appendChild(text)
83                item_elem.appendChild(field)
84
85            root.appendChild(item_elem)
86
87
88        try:
89            data = self.doc.toprettyxml(indent='  ', encoding='utf-8')
90        except UnicodeError, e:
91            # all comments are strings encoded in 'utf-8' and they will properly
92            # saved in xml file, but if we explicitly give 'utf-8' encoding
93            # UnicodeDecodeError will be raised when they have non-ascii chars
94            data = self.doc.toprettyxml(indent='  ')
95
96        self.doc.unlink()
97        return data
98
99class CommentsImporterSection(object):
100    classProvides(ISectionBlueprint)
101    implements(ISection)
102
103    def __init__(self, transmogrifier, name, options, previous):
104        self.previous = previous
105        self.context = transmogrifier.context
106
107        self.pathkey = defaultMatcher(options, 'path-key', name, 'path')
108        self.fileskey = defaultMatcher(options, 'files-key', name, 'files')
109
110        self.dtool = utils.getToolByName(self.context, 'portal_discussion')
111
112    def __iter__(self):
113        for item in self.previous:
114            pathkey = self.pathkey(*item.keys())[0]
115            fileskey = self.fileskey(*item.keys())[0]
116
117            if not (pathkey and fileskey):
118                yield item; continue
119
120            if 'comments' not in item[fileskey]:
121                yield item; continue
122
123            path = item[pathkey]
124            obj = self.context.unrestrictedTraverse(path, None)
125            if obj is None:         # path doesn't exist
126                yield item; continue
127
128            # allow discussion if it wasn't allowed (because we have comments)
129            try:
130                discussion_container = self.dtool.getDiscussionFor(obj)
131            except DiscussionNotAllowed:
132                obj.allow_discussion = True
133                discussion_container = self.dtool.getDiscussionFor(obj)
134
135            data = item[fileskey]['comments']['data']
136            discussion_container._container.clear()
137            for id_, props in self.parseXML(data).items():
138                comment = DiscussionItem.DiscussionItem(id_)
139                discussion_container._container[id_] = comment
140                comment = comment.__of__(discussion_container)
141                self.updateDiscussionItem(comment, props)
142
143            yield item
144
145    def parseXML(self, data):
146        doc = minidom.parseString(data)
147        root = doc.documentElement
148
149        items = {}
150        for child in root.childNodes:
151            if child.nodeName != 'item':
152                continue
153            id_ = str(child.getAttribute('id'))
154            item = items[id_] = {}
155            for field in child.childNodes:
156                if field.nodeName != 'field':
157                    continue
158                name = field.getAttribute('name')
159                # this will be unicode string, encode it?
160                value = ''
161                for node in field.childNodes:
162                    if node.nodeName != '#text':
163                        continue
164                    lines = [line.lstrip() for line in node.nodeValue.splitlines()]
165                    value += '\n'.join(lines)
166                item[name] = value.strip()
167
168        return items
169
170    def updateDiscussionItem(self, item, props):
171        in_reply_to = props['In_reply_to']
172        # if 'In_reply_to' field is string "None" we need to set attribute to None
173        if in_reply_to == 'None':
174            item.in_reply_to = None
175        else:
176            item.in_reply_to = in_reply_to
177
178        item.addCreator(props['Creator'])
179        item.setFormat('text/plain')
180        item.setMetadata(props)
181        item._edit(text=props['Text'])
182        item.setModificationDate(props['Modification_date'])
183        item.indexObject()
Note: See TracBrowser for help on using the repository browser.