Skip to content

Commit

Permalink
plone4 branch imported as a base for further development
Browse files Browse the repository at this point in the history
  • Loading branch information
chervol committed Aug 6, 2010
0 parents commit 55b507c
Show file tree
Hide file tree
Showing 109 changed files with 7,533 additions and 0 deletions.
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
recursive-include quintagroup *
recursive-exclude quintagroup *.py[co]
24 changes: 24 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
***************************************
Export/import transmogrifier blueprints
***************************************

.. contents::

This package contains blueprints for collective.transmogrifier
pipelines, that may be used to export/import Plone site content.
It also overrides GenericSetup ``Content`` step so this package
can be used out-the-box to migrate site content.

Credits
*******

Design and development

- Bohdan Koval _ at Quintagroup_
- Andriy Mylenkyy _ at Quintagroup_
- Vitaliy Podoba
- Volodymyr Cherepanyak _ at Quintagroup_
- Myroslav Opyr _ at Quintagroup_


.. _Quintagroup: http://www.quintagroup.com/
7 changes: 7 additions & 0 deletions TODO.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
TODO
====

- Remove importing of object UIDs

- Rewrite ReferenceExporter adapter as pipeline section and merge code from
ReferenceImporter adapter to reference importer section.
27 changes: 27 additions & 0 deletions docs/HISTORY.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Changelog
=========

0.3 (Unreleased)
----------------

- added sections for export/import of portlet assignments [koval]

0.2 (2010-01-04)
----------------

- the "quintagroup.transmogrifier" namespace removed [koval]

- added interface import/export steps [mylan]

- merged plone21 branch [piv]

- various fixes [piv, mylan, koval]

- history update, release [chervol]


0.1 (2009-11-19)
----------------

- Initial release

6 changes: 6 additions & 0 deletions quintagroup/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
2 changes: 2 additions & 0 deletions quintagroup/transmogrifier/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# this is a package

1 change: 1 addition & 0 deletions quintagroup/transmogrifier/adapters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# i'm a package
21 changes: 21 additions & 0 deletions quintagroup/transmogrifier/adapters/configure.zcml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:five="http://namespaces.zope.org/five">

<!-- 'marshall' adapters -->
<adapter
factory=".exporting.ReferenceExporter"
name="marshall"
/>

<adapter
factory=".importing.ReferenceImporter"
name="marshall"
/>

<adapter
factory=".exporting.CriterionExporter"
name="marshall"
/>

</configure>
84 changes: 84 additions & 0 deletions quintagroup/transmogrifier/adapters/exporting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from xml.dom import minidom

from zope.interface import implements
from zope.component import adapts

from Products.Archetypes import atapi
from Products.Archetypes.interfaces import IBaseObject
from Products.ATContentTypes.interface import IATTopicCriterion
from Products.Marshall.registry import getComponent
from Products.Archetypes import config as atcfg

from collective.transmogrifier.interfaces import ITransmogrifier

from quintagroup.transmogrifier.interfaces import IExportDataCorrector

class ReferenceExporter(object):
""" Add reference fields to XML, generated by Marshall product.
"""
implements(IExportDataCorrector)
adapts(IBaseObject, ITransmogrifier)

def __init__(self, context, transmogrifier):
self.context = context
self.transmogrifier = transmogrifier

def __call__(self, data):
data['data'] = self.exportReferences(data['data'])
return data

def exportReferences(self, xml):
""" Marshall 1.0.0 doesn't export references, do it manually.
"""
if xml is None:
return u"";
doc = minidom.parseString(xml)
root = doc.documentElement
for fname in self.context.Schema().keys():
if not isinstance(self.context.Schema()[fname], atapi.ReferenceField):
continue
values = self.context[fname]
if not values:
continue
elem = doc.createElement("field")
attr = doc.createAttribute("name")
attr.value = fname
elem.setAttributeNode(attr)
if type(values) not in (tuple, list):
values = [values,]
for value in values:
ref = doc.createElement('reference')
uid = doc.createElement('uid')
value = doc.createTextNode(str(value))
uid.appendChild(value)
ref.appendChild(uid)
elem.appendChild(ref)
root.appendChild(elem)
return doc.toxml('utf-8')

class CriterionExporter(ReferenceExporter):
""" Special marshalling adapter for topic criterias.
"""

implements(IExportDataCorrector)
adapts(IATTopicCriterion, ITransmogrifier)

def __init__(self, context, transmogrifier):
self.context = context
self.transmogrifier = transmogrifier
self.marshaller = getComponent('atxml')

def __call__(self, data):
if data['data'] is not None:
return super(CriterionExporter, self).__call__(data)
# Marshall fails when object has UID that is equal to None
# fix it here by setting it to empty string and after marshalling setting back to old value
old_uid_attr = getattr(self.context, atcfg.UUID_ATTR)
setattr(self.context, atcfg.UUID_ATTR, "")

ct, length, xml = self.marshaller.marshall(self.context)
xml = self.exportReferences(xml)
data['data'] = xml

setattr(self.context, atcfg.UUID_ATTR, old_uid_attr)
return data
74 changes: 74 additions & 0 deletions quintagroup/transmogrifier/adapters/importing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import re
from xml.dom import minidom

from zope.interface import implements
from zope.component import adapts

from Products.Archetypes.interfaces import IBaseObject
from Products.Archetypes import atapi

from collective.transmogrifier.interfaces import ITransmogrifier

from quintagroup.transmogrifier.interfaces import IImportDataCorrector

EXISTING_UIDS = {}
REFERENCE_QUEUE = {}

class ReferenceImporter(object):
""" Demarshall content from xml file by using of Marshall product.
"""
implements(IImportDataCorrector)
adapts(IBaseObject, ITransmogrifier)

def __init__(self, context, transmogrifier):
self.context = context
self.transmogrifier = transmogrifier

def __call__(self, data):
# uid = self.context.UID()
uid = self.getUID(data['data'])
if uid:
EXISTING_UIDS[uid] = None
data['data'] = self.importReferences(data['data'])
return data

def getUID(self, xml):
""" Find 'uid' element and get it's value.
"""
start = re.search(r'<uid>', xml)
end = re.search(r'</uid>', xml)
if start and end:
uid = xml[start.end():end.start()]
return uid.strip()
return None

def importReferences(self, data):
""" Marshall 1.0.0 doesn't import references, do it manually.
"""
doc = minidom.parseString(data)
root = doc.documentElement
for fname in self.context.Schema().keys():
if not isinstance(self.context.Schema()[fname], atapi.ReferenceField):
continue
uids = []
validUIDs = True
elements = [i for i in root.getElementsByTagName('field') if i.getAttribute('name') == fname]
if not elements:
# if needed elements are absent skip this field
# update as much as posible fields and don't raise exceptions
continue
elem = elements[0]
for uid_elem in elem.getElementsByTagName('uid'):
value = str(uid_elem.firstChild.nodeValue)
uids.append(value)
if value not in EXISTING_UIDS:
validUIDs = False
if validUIDs:
mutator = self.context.Schema()[fname].getMutator(self.context)
mutator(uids)
else:
suid = str(root.getElementsByTagName('uid')[0].firstChild.nodeValue.strip())
REFERENCE_QUEUE[suid] = {}
REFERENCE_QUEUE[suid][fname] = uids
root.removeChild(elem)
return doc.toxml('utf-8')
Loading

0 comments on commit 55b507c

Please sign in to comment.