Last active
July 20, 2017 11:29
-
-
Save erral/531c3d64954d28f0674885fe605b43ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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