source: products/quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/portlets.py @ 1564

Last change on this file since 1564 was 1564, checked in by koval, 14 years ago

implemented section for importing of portlet assignments

File size: 7.2 KB
Line 
1from xml.dom import minidom
2
3from zope.interface import classProvides, implements, providedBy
4from zope.component import getUtilitiesFor, queryMultiAdapter, getUtility, \
5    getMultiAdapter, adapts
6from zope.component.interfaces import IFactory
7from zope.app.container.interfaces import INameChooser
8
9from plone.portlets.interfaces import ILocalPortletAssignable, IPortletManager,\
10    IPortletAssignmentMapping, IPortletAssignment
11from plone.portlets.constants import CONTEXT_CATEGORY
12from plone.app.portlets.interfaces import IPortletTypeInterface
13from plone.app.portlets.exportimport.interfaces import IPortletAssignmentExportImportHandler
14from plone.app.portlets.exportimport.portlets import PropertyPortletAssignmentExportImportHandler
15from plone.app.portlets.interfaces import IPortletTypeInterface
16
17from collective.transmogrifier.interfaces import ISection, ISectionBlueprint
18from collective.transmogrifier.utils import defaultMatcher
19
20class PortletsExporterSection(object):
21    classProvides(ISectionBlueprint)
22    implements(ISection)
23
24    def __init__(self, transmogrifier, name, options, previous):
25        self.previous = previous
26        self.context = transmogrifier.context
27
28        self.pathkey = defaultMatcher(options, 'path-key', name, 'path')
29        self.fileskey = options.get('files-key', '_files').strip()
30
31        self.doc = minidom.Document()
32
33    def __iter__(self):
34        self.portlet_schemata = dict([(iface, name,) for name, iface in 
35            getUtilitiesFor(IPortletTypeInterface)])
36        self.portlet_managers = getUtilitiesFor(IPortletManager)
37
38        for item in self.previous:
39            pathkey = self.pathkey(*item.keys())[0]
40
41            if not pathkey:
42                yield item; continue
43
44            path = item[pathkey]
45            obj = self.context.unrestrictedTraverse(path, None)
46            if obj is None:         # path doesn't exist
47                yield item; continue
48
49            if ILocalPortletAssignable.providedBy(obj):
50                data = None
51
52                root = self.doc.createElement('portlets')
53                for elem in self.exportAssignments(obj):
54                    root.appendChild(elem)
55                #for elem in self.exportBlacklists(obj)
56                    #root.appendChild(elem)
57                if root.hasChildNodes():
58                    self.doc.appendChild(root)
59                    data = self.doc.toprettyxml(indent='  ', encoding='utf-8')
60                    self.doc.unlink()
61
62                if data:
63                    files = item.setdefault(self.fileskey, {})
64                    item[self.fileskey]['portlets'] = {
65                        'name': '.portlets.xml',
66                        'data': data,
67                    }
68            yield item
69
70    def exportAssignments(self, obj):
71        assignments = []
72        for manager_name, manager in self.portlet_managers:
73            mapping = queryMultiAdapter((obj, manager), IPortletAssignmentMapping)
74            mapping = mapping.__of__(obj)
75
76            for name, assignment in mapping.items():
77                type_ = None
78                for schema in providedBy(assignment).flattened():
79                    type_ = self.portlet_schemata.get(schema, None)
80                    if type_ is not None:
81                        break
82
83                if type_ is not None:
84                    child = self.doc.createElement('assignment')
85                    child.setAttribute('manager', manager_name)
86                    child.setAttribute('category', CONTEXT_CATEGORY)
87                    child.setAttribute('key', '/'.join(obj.getPhysicalPath()))
88                    child.setAttribute('type', type_)
89                    child.setAttribute('name', name)
90
91                    assignment = assignment.__of__(mapping)
92                    # use existing adapter for exporting a portlet assignment
93                    handler = IPortletAssignmentExportImportHandler(assignment)
94                    handler.export_assignment(schema, self.doc, child)
95
96                    assignments.append(child)
97
98        return assignments
99
100class PortletsImporterSection(object):
101    classProvides(ISectionBlueprint)
102    implements(ISection)
103
104    def __init__(self, transmogrifier, name, options, previous):
105        self.previous = previous
106        self.context = transmogrifier.context
107
108        self.pathkey = defaultMatcher(options, 'path-key', name, 'path')
109        self.fileskey = defaultMatcher(options, 'files-key', name, 'files')
110
111    def __iter__(self):
112
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            if 'portlets' not in item[fileskey]:
120                yield item; continue
121
122            path = item[pathkey]
123            obj = self.context.unrestrictedTraverse(path, None)
124            if obj is None:         # path doesn't exist
125                yield item; continue
126
127            if ILocalPortletAssignable.providedBy(obj):
128                data = None
129                data = item[fileskey]['portlets']['data']
130                doc = minidom.parseString(data)
131                root = doc.documentElement
132                for elem in root.childNodes:
133                    if elem.nodeName == 'assignment':
134                        self.importAssignment(obj, elem)
135                    #elif elem.nodeName == 'blacklist':
136                        #self.importBlacklist(obj, elem)
137
138            yield item
139
140    def importAssignment(self, obj, node):
141        """ Import an assignment from a node
142        """
143        # 1. Determine the assignment mapping and the name
144        manager_name = node.getAttribute('manager')
145        category = node.getAttribute('category')
146
147        manager = getUtility(IPortletManager, manager_name)
148        mapping = getMultiAdapter((obj, manager), IPortletAssignmentMapping)
149
150        # 2. Either find or create the assignment
151        assignment = None
152        name = node.getAttribute('name')
153        if name:
154            assignment = mapping.get(name, None)
155
156        type_ = node.getAttribute('type')
157
158        if assignment is None:
159            portlet_factory = getUtility(IFactory, name=type_)
160            assignment = portlet_factory()
161
162            if not name:
163                chooser = INameChooser(mapping)
164                name = chooser.chooseName(None, assignment)
165
166            mapping[name] = assignment
167
168        # aq-wrap it so that complex fields will work
169        assignment = assignment.__of__(obj)
170
171        # 3. Use an adapter to update the portlet settings
172        portlet_interface = getUtility(IPortletTypeInterface, name=type_)
173        assignment_handler = IPortletAssignmentExportImportHandler(assignment)
174        assignment_handler.import_assignment(portlet_interface, node)
175
176class PortletAssignmentExportImportHandler(PropertyPortletAssignmentExportImportHandler):
177    """ This adapter is needed because original fails to handle text from
178        pretty printed XML file.
179    """
180    adapts(IPortletAssignment)
181
182    def extract_text(self, node):
183        text = super(PortletAssignmentExportImportHandler, self).extract_text(node)
184        # strip text to remove newlines and space character from the beginning
185        # and the end
186        return text.strip()
Note: See TracBrowser for help on using the repository browser.