[275] | 1 | import os.path |
---|
| 2 | from xml.dom import minidom |
---|
| 3 | |
---|
| 4 | from zope.interface import classProvides, implements |
---|
| 5 | |
---|
| 6 | from collective.transmogrifier.interfaces import ISection, ISectionBlueprint |
---|
| 7 | from collective.transmogrifier.utils import defaultMatcher |
---|
| 8 | |
---|
| 9 | class ManifestSection(object): |
---|
| 10 | classProvides(ISectionBlueprint) |
---|
| 11 | implements(ISection) |
---|
| 12 | |
---|
| 13 | def __init__(self, transmogrifier, name, options, previous): |
---|
| 14 | self.previous = previous |
---|
| 15 | self.context = transmogrifier.context |
---|
| 16 | |
---|
| 17 | self.entrieskey = defaultMatcher(options, 'entries-key', name, 'entries') |
---|
| 18 | |
---|
| 19 | def __iter__(self): |
---|
| 20 | for item in self.previous: |
---|
| 21 | entrieskey = self.entrieskey(*item.keys())[0] |
---|
| 22 | if not entrieskey: |
---|
| 23 | yield item; continue |
---|
| 24 | |
---|
| 25 | manifest = self.createManifest(item[entrieskey]) |
---|
| 26 | |
---|
| 27 | if manifest: |
---|
| 28 | files = item.setdefault('_files', {}) |
---|
| 29 | item['_files']['manifest'] = { |
---|
| 30 | 'name': '.objects.xml', |
---|
| 31 | 'data': manifest, |
---|
| 32 | } |
---|
| 33 | |
---|
| 34 | yield item |
---|
| 35 | |
---|
| 36 | def createManifest(self, data): |
---|
| 37 | if not data: |
---|
| 38 | return None |
---|
| 39 | manifest = '<?xml version="1.0" ?>\n<manifest>\n' |
---|
| 40 | for obj_id, obj_type in data: |
---|
| 41 | manifest += ' <record type="%s">%s</record>\n' % (obj_type, obj_id) |
---|
| 42 | manifest += "</manifest>\n" |
---|
| 43 | return manifest |
---|
| 44 | |
---|
| 45 | class ManifestImportSection(object): |
---|
| 46 | classProvides(ISectionBlueprint) |
---|
| 47 | implements(ISection) |
---|
| 48 | |
---|
| 49 | def __init__(self, transmogrifier, name, options, previous): |
---|
| 50 | self.previous = previous |
---|
| 51 | self.context = transmogrifier.context |
---|
| 52 | |
---|
| 53 | self.pathkey = defaultMatcher(options, 'path-key', name, 'path') |
---|
| 54 | self.fileskey = defaultMatcher(options, 'files-key', name, 'files') |
---|
| 55 | |
---|
| 56 | # we need this dictionary to store manifest data, because reader section |
---|
| 57 | # uses recursion when walking through content folders |
---|
| 58 | self.manifests = {} |
---|
| 59 | |
---|
| 60 | def __iter__(self): |
---|
| 61 | for item in self.previous: |
---|
| 62 | pathkey = self.pathkey(*item.keys())[0] |
---|
| 63 | fileskey = self.fileskey(*item.keys())[0] |
---|
| 64 | |
---|
| 65 | # skip items without path |
---|
| 66 | if not pathkey: continue |
---|
| 67 | |
---|
| 68 | path = item[pathkey] |
---|
| 69 | |
---|
| 70 | if path != '': |
---|
| 71 | parent, item_id = os.path.split(path) |
---|
| 72 | manifest = self.manifests.get(parent, {}) |
---|
| 73 | |
---|
| 74 | # skip that are not listed in their parent's manifest |
---|
| 75 | if item_id not in manifest: continue |
---|
| 76 | |
---|
| 77 | item['_type'] = manifest.pop(item_id) |
---|
| 78 | # remove empty manifest dict |
---|
| 79 | if not manifest: |
---|
| 80 | del self.manifests[parent] |
---|
| 81 | |
---|
| 82 | # this item is folderish - parse manifest |
---|
| 83 | if fileskey and 'manifest' in item[fileskey]: |
---|
| 84 | self.extractManifest(path, item[fileskey]['manifest']['data']) |
---|
| 85 | |
---|
| 86 | yield item |
---|
| 87 | |
---|
| 88 | def extractManifest(self, path, data): |
---|
| 89 | doc = minidom.parseString(data) |
---|
| 90 | objects = {} |
---|
| 91 | for record in doc.getElementsByTagName('record'): |
---|
| 92 | type_ = str(record.getAttribute('type')) |
---|
| 93 | object_id = str(record.firstChild.nodeValue.strip()) |
---|
| 94 | objects[object_id] = type_ |
---|
| 95 | self.manifests[path] = objects |
---|