Skip to content

Instantly share code, notes, and snippets.

@erral
Last active July 20, 2017 11:29
Show Gist options
  • Save erral/531c3d64954d28f0674885fe605b43ef to your computer and use it in GitHub Desktop.
Save erral/531c3d64954d28f0674885fe605b43ef to your computer and use it in GitHub Desktop.
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser">
<browser:page
for="*"
name="copy-content-to"
class=".copier.CopyContentToLanguage"
permission="cmf.ManagePortal"
/>
</configure>
from plone.dexterity.interfaces import IDexterityContent
from Products.CMFCore.utils import getToolByName
from plone.app.textfield.value import RichTextValue
from zope.schema import getFieldsInOrder
from plone.behavior.interfaces import IBehaviorAssignable
from plone.app.multilingual.interfaces import ITranslationManager
from plone.app.multilingual import _
from Products.statusmessages.interfaces import IStatusMessage
from plone.directives import form
from zope.interface import Interface
from z3c.form import field, button
from zope import schema
from zope.component import queryMultiAdapter
from plone.uuid.interfaces import IUUID
from plone.app.layout.navigation.interfaces import INavigationRoot
class ICopyContentToLanguage(Interface):
context_element = schema.Bool(
title=_(u'Include context element?'),
description=_(u'If selected, the context element will be translated'),
default=False,
)
contents_too = schema.Bool(
title=_(u'Include the contents?'),
description=_(u'If selected, all the subobjects of this content will also be translated')
)
target_languages = schema.List(
title=_(u'Target languages'),
description=_(u'Select into which languages the translation will be made'),
value_type=schema.Choice(
title=_(u'Target languages'),
vocabulary=u'ela5.content.CopierAvailableLanguageVocabularyFactory'
),
default=[],
)
class CopyContentToLanguage(form.Form):
fields = field.Fields(ICopyContentToLanguage)
label = _(u'Copy the contents of this objects and its subobjects '
u'to the selected language/country')
ignoreContext = True
@button.buttonAndHandler(_(u'Copy content'))
def copy_content_to(self, action):
from logging import getLogger
log = getLogger('copy_content_to')
data, errors = self.extractData()
if errors:
self.status = self.formErrorsMessage
return
target_languages = data.get('target_languages', [])
if data.get('context_element', False):
self.copy_contents_of(self.context, target_languages)
#self.copy_related_fields(self.context, target_languages)
if data.get('contents_too', False):
pcat = getToolByName(self.context, 'portal_catalog')
brains = pcat(path='/'.join(self.context.getPhysicalPath()))
list_of_items = []
for br in brains:
list_of_items.append(br.getObject())
list_of_items.sort(lambda x, y: cmp(len(x.getPhysicalPath()),
len(y.getPhysicalPath()))
)
for obj in list_of_items:
if obj != self.context:
self.copy_contents_of(obj, target_languages)
###### for the related fields #######################
# for obj in list_of_items:
# self.copy_related_fields(obj, target_languages)
log.info('done')
msg = _(u'Contents copied successfuly')
IStatusMessage(self.request).add(msg, type='info')
return
def copy_related_fields(self, obj, target_languages):
from logging import getLogger
log = getLogger('copy_related_fields')
try:
fields = schema.getFieldsInOrder(obj.getTypeInfo().lookupSchema())
except AttributeError, e:
log.info('Error: %s' % '/'.join(obj.getPhysicalPath()))
log.exception(e)
pcat = getToolByName(self.context, 'portal_catalog')
for key, value in fields:
value = value.get(obj)
if type(value) == type([]):
manager = ITranslationManager(obj)
for language in target_languages:
translated_obj = manager.get_translation(language)
uid_list = []
for uid in value:
element = pcat(UID=uid, Language=obj.Language())
if element:
manager = ITranslationManager(element[0].getObject())
element_trans = manager.get_translation(language)
if element_trans:
uid_list.append(IUUID(element_trans))
if uid_list:
setattr(translated_obj, key, uid_list)
translated_obj.reindexObject()
def copy_contents_of(self, item, target_languages):
from logging import getLogger
log = getLogger('copy_contents_of')
for language in target_languages:
manager = ITranslationManager(item)
if not manager.has_translation(language):
manager.add_translation(language)
log.info('Created translation for %s: %s' %
('/'.join(item.getPhysicalPath()),
language,
)
)
import transaction
transaction.commit()
translated = manager.get_translation(language)
self.copy_fields(item, translated)
self.copy_seo_properties(item, translated)
if isinstance(translated.id, unicode):
translated.id = translated.id.encode('utf-8')
log.info('Id changed to UTF-8: %s' % '/'.join(translated.getPhysicalPath()))
if item.hasProperty('layout'):
if not translated.hasProperty('layout'):
translated.manage_addProperty('layout', item.getProperty('layout'), 'string')
else:
translated.manage_changeProperties(layout=item.getProperty('layout'))
if item.hasProperty('default_page'):
if not translated.hasProperty('default_page'):
translated.manage_addProperty('default_page', item.getProperty('default_page'), 'string')
else:
translated.manage_changeProperties(layout=item.getProperty('default_page'))
translated.reindexObject()
def copy_fields(self, source, target):
if IDexterityContent.providedBy(source):
self.copy_fields_dexterity(source, target)
else:
self.copy_fields_at(source, target)
def copy_fields_at(self, source, target):
from logging import getLogger
log = getLogger('copy_fields_at')
for field in source.Schema().fields():
fieldname = field.__name__
if fieldname.lower() == 'language':
# skip language
log.info('Skipped %s' % fieldname)
continue
value = field.get(source)
target_field = target.getField(fieldname, target)
if target_field.writeable(target):
if isinstance(value, unicode):
value = value.encode('utf-8')
if value:
target_field.set(target, value)
log.info('Set attribute %s in %s' % (fieldname, '/'.join(target.getPhysicalPath())))
else:
log.info('Not writeable. Can not set value for field %s in %s.' % (fieldname, '/'.join(target.getPhysicalPath())))
def copy_fields_dexterity(self, source, target):
# Copy the content from the canonical fields
from logging import getLogger
log = getLogger('copy_fields_dexterity')
try:
fields = schema.getFieldsInOrder(source.getTypeInfo().lookupSchema())
except AttributeError, e:
log.info('Error: %s' % '/'.join(source.getPhysicalPath()))
log.exception(e)
return
for key, value in fields:
if key.lower() == 'language':
# skip language
log.info('Skipped %s' % key)
continue
self.change_content(source, target, key)
# Copy the contents from behaviors
behavior_assignable = IBehaviorAssignable(source)
if behavior_assignable:
behaviors = behavior_assignable.enumerateBehaviors()
for behavior in behaviors:
for key, value in getFieldsInOrder(behavior.interface):
if key.lower() == 'language':
# skip language
log.info('Skipped %s' % key)
continue
self.change_content_for_behavior(source, target, key, behavior.interface)
def copy_seo_properties(self, source, target):
from logging import getLogger
seo_context = queryMultiAdapter((self.context, self.context.REQUEST),
name='seo_context')
log = getLogger('copy_seo_properties')
for k, v in source.propertyItems():
if k.startswith('qSEO_'):
if target.hasProperty(k):
target.manage_changeProperties({k: source.getProperty(k)})
path = '/'.join(source.getPhysicalPath())
log.info('Changed property %s for %s' % (k, path))
else:
if k=='qSEO_keywords':
target.manage_addProperty(k, source.getProperty(k), 'lines')
else:
target.manage_addProperty(k, source.getProperty(k), 'string')
def change_content(self, source, target, key):
from logging import getLogger
log = getLogger('change_content')
value = getattr(getattr(source, key), 'raw', getattr(source, key))
try:
if getattr(getattr(source, key), 'raw', None) is not None:
setattr(target, key, RichTextValue(value, 'text/html', 'text/x-html-safe'))
if hasattr(source, 'getPhysicalPath'):
log.info('Set attribute %s in %s' % (key, '/'.join(target.getPhysicalPath())))
else:
log.info('Set attribute %s in %s' % (key, '/'.join(target.context.getPhysicalPath())))
else:
setattr(target, key, value)
if hasattr(source, 'getPhysicalPath'):
log.info('Set attribute %s in %s' % (key, '/'.join(target.getPhysicalPath())))
else:
log.info('Set attribute %s in %s' % (key, '/'.join(target.context.getPhysicalPath())))
except Exception, e:
log.info('Error setting attribute %s on %s' % (key, target))
log.exception(e)
def change_content_for_behavior(self, source, target, key, behavior):
behaviored_source = behavior(source)
behaviored_target = behavior(target)
self.change_content(behaviored_source, behaviored_target, key)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment