SHARE
TWEET

portal_transforms import/export try 2

a guest Sep 20th, 2019 97 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. from persistent.mapping import PersistentMapping
  2. from Products.CMFCore.exportimport.content import importSiteStructure as \
  3.      orig_importSiteStructure
  4. from Products.CMFCore.utils import getToolByName
  5. from Products.GenericSetup.utils import XMLAdapterBase
  6. from Products.GenericSetup.utils import PropertyManagerHelpers
  7. from Products.GenericSetup.utils import exportObjects
  8. from Products.GenericSetup.utils import importObjects
  9. from Products.MimetypesRegistry.common import MimeTypeException
  10. from Products.PortalTransforms.Transform import Transform
  11. from Products.PortalTransforms.chain import TransformsChain
  12.  
  13.  
  14. # Support for declarative export / import of the 'portal_transforms' tool.
  15. #
  16. # XXX: The following code should be in Products.PortalTransforms.  See
  17. #      https://dev.plone.org/ticket/12785
  18. #
  19. # Credit to Tres Seaver @tseaver
  20. class PortalTransformsToolXMLAdapter(XMLAdapterBase, PropertyManagerHelpers):
  21.     """XML im- and exporter for PortalTransforms tool.
  22.  
  23.    <object name="portal_transforms" meta_type="Portal Transforms Tool">
  24.     <property name="xxx">SIMPLE VALUE</property>
  25.     <property name="yyy">
  26.      <element value="SIMPLE VALUE">
  27.      ...
  28.     </property>
  29.     ...
  30.     <transform name="abc" module="foo.bar.doBaz"/>
  31.     ...
  32.     <chain name="pqr" transforms="abc def ghi"/>
  33.     ...
  34.     <mimetype input="foo/bar">
  35.      <target output="baz/bam" name="abc"/>
  36.      ...
  37.     </mimetype>
  38.     ...
  39.     <policy output="baz/bam" transforms="def ghi"/>
  40.     ...
  41.    </object>
  42.    """
  43.     _LOGGER_ID = 'PortalTransforms.tool'
  44.  
  45.     _PYTHON_CODE_ATTRS = ['CLOSE_COMMENT',
  46.                           'CLOSE_ERRORTOKEN',
  47.                           'CLOSE_KEYWORD',
  48.                           'CLOSE_NAME',
  49.                           'CLOSE_NUMBER',
  50.                           'CLOSE_OP',
  51.                           'CLOSE_STRING',
  52.                           'CLOSE_TEXT',
  53.                           'OPEN_COMMENT',
  54.                           'OPEN_ERRORTOKEN',
  55.                           'OPEN_KEYWORD',
  56.                           'OPEN_NAME',
  57.                           'OPEN_NUMBER',
  58.                           'OPEN_OP',
  59.                           'OPEN_STRING',
  60.                           'OPEN_TEXT',
  61.                          ]
  62.  
  63.     def _extractTransforms(self):
  64.         fragment = self._doc.createDocumentFragment()
  65.         for key, value in sorted(self.context.objectItems('Transform')):
  66.             node = self._doc.createElement('transform')
  67.             node.setAttribute('name', key)
  68.             node.setAttribute('module', value.module)
  69.             fragment.appendChild(node)
  70.             c_nodes = []
  71.  
  72.             # generic
  73.             for input_mt in value._config.get('inputs', ()):
  74.                 c_nodes.append(
  75.                     ('input', [('mimetype', input_mt)]))
  76.  
  77.             output_mt = value._config.get('output')
  78.             if output_mt is not None:
  79.                 c_nodes.append(
  80.                     ('output', [('mimetype', output_mt)]))
  81.  
  82.             # html_to_web_intelligent_plain_text and
  83.             # web_intelligent_plain_text_to_html
  84.             tab_width = value._config.get('tab_width')
  85.             if tab_width is not None:
  86.                 c_nodes.append(
  87.                     ('tab_width', [('value', str(tab_width))]))
  88.  
  89.             # rest_to_html
  90.             report_level = value._config.get('report_level')
  91.             if report_level is not None:
  92.                 c_nodes.append(
  93.                     ('report_level', [('value', str(report_level))]))
  94.  
  95.             init_hdr_level = value._config.get('initial_header_level')
  96.             if init_hdr_level is not None:
  97.                 c_nodes.append(
  98.                     ('initial_header_level', [('value', str(init_hdr_level))]))
  99.  
  100.             # safe_html
  101.             disable_transform = value._config.get('disable_transform')
  102.             if disable_transform is not None:
  103.                 c_nodes.append(
  104.                     ('disable_transform', [('value', str(disable_transform))]))
  105.  
  106.             remove_javascript = value._config.get('remove_javascript')
  107.             if remove_javascript is not None:
  108.                 c_nodes.append(
  109.                     ('remove_javascript', [('value', str(remove_javascript))]))
  110.  
  111.             class_blacklist = sorted(value._config.get('class_blacklist', ()))
  112.             for klass in class_blacklist:
  113.                 c_nodes.append(
  114.                     ('class_blacklist', [('class', klass)]))
  115.  
  116.             style_whitelist = sorted(value._config.get('style_whitelist', ()))
  117.             for style in style_whitelist:
  118.                 c_nodes.append(
  119.                     ('style_whitelist', [('style', style)]))
  120.  
  121.             stripped_attributes = sorted(
  122.                                 value._config.get('stripped_attributes', ()))
  123.             for attr in stripped_attributes:
  124.                 c_nodes.append(
  125.                     ('stripped', [('attr', attr)]))
  126.  
  127.             stripped_combo = value._config.get('stripped_combinations', {})
  128.             for combo, attrs in sorted(stripped_combo.items()):
  129.                 c_nodes.append(
  130.                     ('stripped', [('combo', combo), ('attrs', attrs)]))
  131.  
  132.             nasty = value._config.get('nasty_tags', {})
  133.             for key, is_long in sorted(nasty.items()):
  134.                 c_nodes.append(
  135.                     ('nasty_tag', [('tag', key),
  136.                                    ('long', str(is_long))]))
  137.  
  138.             valid = value._config.get('valid_tags', {})
  139.             for key, is_long in sorted(valid.items()):
  140.                 c_nodes.append(
  141.                     ('valid_tag', [('tag', key),
  142.                                    ('long', str(is_long))]))
  143.  
  144.             for c_key in self._PYTHON_CODE_ATTRS:
  145.                 c_value = value._config.get(c_key)
  146.                 if c_value is not None:
  147.                     c_nodes.append((c_key, [('value', c_value)]))
  148.  
  149.             for typ, attrs in c_nodes:
  150.                 cfg = self._doc.createElement(typ)
  151.                 for k, v in attrs:
  152.                     cfg.setAttribute(k, v)
  153.                 node.appendChild(cfg)
  154.  
  155.         return fragment
  156.  
  157.     def _extractChains(self):
  158.         fragment = self._doc.createDocumentFragment()
  159.         for key, value in sorted(self.context.objectItems('TransformsChain')):
  160.             node = self._doc.createElement('chain')
  161.             node.setAttribute('name', key)
  162.             node.setAttribute('transforms', ' '.join(value._object_ids))
  163.             fragment.appendChild(node)
  164.         return fragment
  165.  
  166.     def _extractMTMap(self):
  167.         fragment = self._doc.createDocumentFragment()
  168.         for input_mt, segments in sorted(self.context._mtmap.items()):
  169.             node = self._doc.createElement('mimetype')
  170.             node.setAttribute('input', input_mt)
  171.             for output_mt, transforms in segments.items():
  172.                 sub = self._doc.createElement('target')
  173.                 sub.setAttribute('output', output_mt)
  174.                 t_ids = [x.id for x in transforms]
  175.                 sub.setAttribute('transforms', ' '.join(t_ids))
  176.                 node.appendChild(sub)
  177.             fragment.appendChild(node)
  178.         return fragment
  179.  
  180.     def _extractPolicies(self):
  181.         fragment = self._doc.createDocumentFragment()
  182.         for output_mt, required in sorted(self.context.listPolicies()):
  183.             node = self._doc.createElement('policy')
  184.             node.setAttribute('output', output_mt)
  185.             node.setAttribute('requirement', ' '.join(required))
  186.             fragment.appendChild(node)
  187.         return fragment
  188.  
  189.     def _exportNode(self):
  190.         """Export the object as a DOM node.
  191.        """
  192.         node = self._getObjectNode('object')
  193.         node.appendChild(self._extractProperties())
  194.         node.appendChild(self._extractTransforms())
  195.         node.appendChild(self._extractChains())
  196.         node.appendChild(self._extractMTMap())
  197.         node.appendChild(self._extractPolicies())
  198.  
  199.         self._logger.info('Tool exported.')
  200.         return node
  201.  
  202.  
  203.  
  204.     def _initTransforms(self, node):
  205.         for child in node.childNodes:
  206.             if child.nodeName == 'transform':
  207.                 name = child.getAttribute('name')
  208.                 module = child.getAttribute('module')
  209.                 transform = Transform(name, module)
  210.                 cfg = transform._config
  211.                 cleared = {}
  212.                 for grand in child.childNodes:
  213.                     gga = getattr(grand, 'getAttribute', None)
  214.                     if gga is None:
  215.                         continue
  216.                     if grand.nodeName == 'input':
  217.                         inputs = cfg.setdefault('inputs', [])
  218.                         if 'inputs' not in cleared:
  219.                             inputs[:] = []
  220.                             cleared['inputs'] = 1
  221.                         inputs.append(gga('mimetype'))
  222.                     if grand.nodeName == 'output':
  223.                         cfg['output'] = gga('mimetype')
  224.                     if grand.nodeName == 'tab_width':
  225.                         cfg['tab_width'] = int(gga('value'))
  226.                     if grand.nodeName == 'report_level':
  227.                         cfg['report_level'] = int(gga('value'))
  228.                     if grand.nodeName == 'initial_header_level':
  229.                         cfg['initial_header_level'] = int(gga('value'))
  230.                     if grand.nodeName == 'disable_transform':
  231.                         cfg['disable_transform'] = int(gga('value'))
  232.                     if grand.nodeName == 'remove_javascript':
  233.                         cfg['remove_javascript'] = int(gga('value'))
  234.                     if grand.nodeName == 'class_blacklist':
  235.                         blist = cfg.setdefault('class_blacklist', [])
  236.                         if 'class_blacklist' not in cleared:
  237.                             blist[:] = []
  238.                             cleared['class_blacklist'] = 1
  239.                         blist.append(gga('class'))
  240.                     if grand.nodeName == 'style_whitelist':
  241.                         wlist = cfg.setdefault('style_whitelist', [])
  242.                         if 'style_whitelist' not in cleared:
  243.                             wlist[:] = []
  244.                             cleared['style_whitelist'] = 1
  245.                         wlist.append(gga('style'))
  246.                     if grand.nodeName == 'stripped':
  247.                         attr = gga('attr')
  248.                         if attr is not None:
  249.                             slist = cfg.setdefault('stripped_attributes', [])
  250.                             if 'stripped_attributes' not in cleared:
  251.                                 slist[:] = []
  252.                                 cleared['stripped_attributes'] = 1
  253.                             slist.append(attr)
  254.                         else:
  255.                             sdict = cfg.setdefault('stripped_combinations', {})
  256.                             if 'stripped_combinations' not in cleared:
  257.                                 sdict.clear()
  258.                                 cleared['stripped_combinations'] = 1
  259.                             combo = gga('combo')
  260.                             attrs = gga('attrs')
  261.                             sdict[combo] = attrs
  262.                     if grand.nodeName == 'nasty_tag':
  263.                         ndict = cfg.setdefault('nasty_tags', {})
  264.                         if 'nasty_tags' not in cleared:
  265.                             ndict.clear()
  266.                             cleared['nasty_tags'] = 1
  267.                         tag = gga('tag')
  268.                         is_long = int(gga('long'))
  269.                         ndict[tag] = is_long
  270.                     if grand.nodeName == 'valid_tag':
  271.                         vdict = cfg.setdefault('valid_tags', {})
  272.                         if 'valid_tags' not in cleared:
  273.                             vdict.clear()
  274.                             cleared['valid_tags'] = 1
  275.                         tag = gga('tag')
  276.                         is_long = int(gga('long'))
  277.                         vdict[tag] = is_long
  278.                     for aname in self._PYTHON_CODE_ATTRS:
  279.                         if grand.nodeName == aname:
  280.                             cfg[aname] = gga('value')
  281.                 self.context._setObject(str(name), transform)
  282.                 try:
  283.                     self.context._mapTransform(transform)
  284.                 except MimeTypeException:
  285.                     # don't choke on broken transforms
  286.                     pass
  287.  
  288.     def _initChains(self, node):
  289.         for child in node.childNodes:
  290.             if child.nodeName == 'chain':
  291.                 name = child.getAttribute('name')
  292.                 description = '' # should be in XML
  293.                 transforms = child.getAttribute('transforms').split()
  294.                 chain = TransformsChain(id, description, transforms)
  295.                 self.context._setObject(id, chain)
  296.                 self.context._mapTransform(chain)
  297.  
  298.     def _initMTMap(self, node):
  299.         # This should be handled by the '_mapTransform' call above.
  300.         pass
  301.  
  302.     def _initPolicies(self, node):
  303.         for child in node.childNodes:
  304.             if child.nodeName == 'policy':
  305.                 output = child.getAttribute('output')
  306.                 transforms = child.getAttribute('transforms').split()
  307.                 self.context.manage_addPolicy(output, transforms)
  308.  
  309.     def _importNode(self, node):
  310.         """Import the object from the DOM node.
  311.        """
  312.         if self.environ.shouldPurge():
  313.             ids = self.context.objectIds()
  314.             for id in ids:
  315.                 self.context._delOb(id)
  316.             # suppress 'manage_beforeDelete' crap
  317.             self.context._objects = ()
  318.             self.context._mtmap = PersistentMapping()
  319.             self.context._policies = PersistentMapping()
  320.             self._purgeProperties()
  321.  
  322.         self._initProperties(node)
  323.         self._initTransforms(node)
  324.         self._initChains(node)
  325.         self._initPolicies(node)
  326.         self._initMTMap(node)
  327.  
  328.         self._logger.info('Tool imported.')
  329.  
  330. def importPortalTransformsTool(context):
  331.     """Import PortalTransforms tool.
  332.    """
  333.     site = context.getSite()
  334.     tool = getToolByName(site, 'portal_transforms')
  335.     importObjects(tool, '', context)
  336.  
  337. def exportPortalTransformsTool(context):
  338.     """Export PortalTransforms tool.
  339.    """
  340.     site = context.getSite()
  341.     tool = getToolByName(site, 'portal_transforms', None)
  342.     if tool is None:
  343.         return
  344.     exportObjects(tool, '', context)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top