def post_validate(self, REQUEST, errors): """Check to make sure that either an internal or external link was supplied.""" if not REQUEST.form.get('externalLink') and not REQUEST.form.get( 'internalLink'): xlink = REQUEST.get('externalLink', None) ilink = REQUEST.get('internalLink', None) if (not xlink and not ilink): errors['externalLink'] = _( "error_externallink_internallink_required", default= u'Please provide the external URL, or fill the "Internal link" field' ) errors['internalLink'] = _( "error_internallink_externallink_required", default= u'Please provide the internal link, or fill the "External link" field' ) return errors if REQUEST.form.get('externalLink') and REQUEST.form.get( 'internalLink'): errors['externalLink'] = _( "error_internallink_externallink_doubled", default= u'You must select an internal link or enter an external link. You cannot have both.' ) return errors
class MigrateBlobs(formbase.PageForm): form_fields = form.FormFields(IMigrateBlobsSchema) label = _(u'BLOBs Migration') description = _(u'Migrate Smart Link, making it use plone.app.blob') @form.action(_(u'Migrate')) def actionMigrate(self, action, data): if MIGRATION_MODULE: messages = migrateSmartLink(self.context) i = 0 for m in messages: i += 1 IStatusMessage(self.request).addStatusMessage(m, type='info') portal = getToolByName(self.context, 'portal_url').getPortalObject() portal.plone_utils.addPortalMessage( _('sequence_help_message', default=u"$num element(s) migrated", mapping={'num': i})) return self.request.response.redirect(self.context.absolute_url()) else: output = _( u'migration_error_msg', default= u'You need to install "Products.contentmigration" product for perform the task' ) IStatusMessage(self.request).addStatusMessage(output, type='error') return self.request.response.redirect( self.context.absolute_url() + '/@@blob-smartlink-migration') @form.action(_(u'Cancel')) def actionCancel(self, action, data): return self.request.response.redirect(self.context.absolute_url())
def _fixURLs(self): paths = self.request.form['path'] context = self.context for path in paths: obj = context.restrictedTraverse(path, None) if obj: linkNormalizerUtility = getUtility(ILinkNormalizerUtility) # use getRemoteUrl below, not getExternalLink; in this way we can fix # also links that loose all internal/external information remote = linkNormalizerUtility.toCurrent(obj.getRemoteUrl()) linked = self.findInternalByURL(remote) if linked: obj.edit(internalLink=linked.UID(), externalLink='') self._status.append({'msg': _('link_fixed_message', default=u'External link fixed: ${origin} now links ${linked}', mapping={'origin': obj.absolute_url_path(), 'linked': linked.absolute_url_path()}), 'type': 'info'}) else: self._status.append({'msg': _('link_fixed_not_found_message', default=u'Cannot find internal content at ${linked}', mapping={'linked': remote}), 'type': 'error'}) else: self._status.append({'msg': _('link_fixed_not_found_message', default=u'Cannot find internal content at ${linked}', mapping={'linked': path}), 'type': 'error'}) return paths
def saveFields(self, action, data): CheckAuthenticator(self.request) if form.applyChanges(self.context, self.form_fields, data, self.adapters): self.status = _(u"Changes saved.") self._on_save(data) else: self.status = _(u"No changes made.")
def handle_cancel_action(self, action, data): IStatusMessage(self.request).addStatusMessage(_("Changes canceled."), type="info") url = getMultiAdapter((self.context, self.request), name='absolute_url')() self.request.response.redirect(url + '/@@smartlink-config') return ''
def smartLinkToATLink(context): """Run this to recover original Plone ATLink""" portal = context.getSite() if context.readDataFile( 'redturtle.smartlink_smartLinkToATLink.txt') is None: return try: from redturtle.smartlink.migrator import migrateSmartLinkToLink logger.info("Starting migration of Smart Link back to ATLink") messages = migrateSmartLinkToLink(portal) i = 0 for m in messages: i += 1 logger.info(m) portal.plone_utils.addPortalMessage(m, type="warning") portal.plone_utils.addPortalMessage( _('sequence_help_message', default=u"$num element(s) migrated", mapping={'num': i})) logger.info("Done") except ImportError: logger.error( "Can't do anything. Check if Products.contentmigration is installed" )
def actionMigrate(self, action, data): if MIGRATION_MODULE: messages = migrateSmartLink(self.context) i = 0 for m in messages: i+=1 IStatusMessage(self.request).addStatusMessage(m, type='info') portal = getToolByName(self.context, 'portal_url').getPortalObject() portal.plone_utils.addPortalMessage(_('sequence_help_message', default=u"$num element(s) migrated", mapping={'num': i})) return self.request.response.redirect(self.context.absolute_url()) else: output = _(u'migration_error_msg', default=u'You need to install "Products.contentmigration" product for perform the task') IStatusMessage(self.request).addStatusMessage(output, type='error') return self.request.response.redirect(self.context.absolute_url()+'/@@blob-smartlink-migration')
def _fixURLs(self): paths = self.request.form['path'] context = self.context for path in paths: obj = context.restrictedTraverse(path, None) if obj: linkNormalizerUtility = getUtility(ILinkNormalizerUtility) # use getRemoteUrl below, not getExternalLink; in this way we can fix # also links that loose all internal/external information remote = linkNormalizerUtility.toCurrent(obj.getRemoteUrl()) linked = self.findInternalByURL(remote) if linked: obj.edit(internalLink=linked.UID(), externalLink='') self._status.append({ 'msg': _('link_fixed_message', default= u'External link fixed: ${origin} now links ${linked}', mapping={ 'origin': obj.absolute_url_path(), 'linked': linked.absolute_url_path() }), 'type': 'info' }) else: self._status.append({ 'msg': _('link_fixed_not_found_message', default=u'Cannot find internal content at ${linked}', mapping={'linked': remote}), 'type': 'error' }) else: self._status.append({ 'msg': _('link_fixed_not_found_message', default=u'Cannot find internal content at ${linked}', mapping={'linked': path}), 'type': 'error' }) return paths
def actionMigrate(self, action, data): output = migrateLinkToSmartLink(self.context) cnt = 0 for l in output: cnt+=1 IStatusMessage(self.request).addStatusMessage(l, type='info') IStatusMessage(self.request).addStatusMessage(_('update_count_message', default="${count} elements updated", mapping={'count': cnt}), type='info') return self.request.response.redirect(self.context.absolute_url() + '/@@smartlink-config')
def uninstall(portal, reinstall=False): setup_tool = portal.portal_setup setup_tool.runAllImportStepsFromProfile("profile-redturtle.smartlink:uninstall") if getFSVersionTuple()[0] >= 4: unregisterIcon(portal) if not reinstall: removeSmartLinkMarks(portal) setup_tool.runAllImportStepsFromProfile("profile-redturtle.smartlink:smartLinkToATLink") logger.info("...done. Thanks you for using me!") portal.plone_utils.addPortalMessage( _("uninstall_info", default=u"All of yours Smart Link contents has been transformed back to Plone ATLink"), type="info", )
def actionMigrate(self, action, data): output = migrateLinkToSmartLink(self.context) cnt = 0 for l in output: cnt += 1 IStatusMessage(self.request).addStatusMessage(l, type='info') IStatusMessage(self.request).addStatusMessage(_( 'update_count_message', default="${count} elements updated", mapping={'count': cnt}), type='info') return self.request.response.redirect(self.context.absolute_url() + '/@@smartlink-config')
def install(portal, reinstall=False): setup_tool = portal.portal_setup setup_tool.runAllImportStepsFromProfile( 'profile-redturtle.smartlink:default') if not reinstall: portal.plone_utils.addPortalMessage(_( 'install_info', default= u'Starting from now, all Links created in this site will be Smart Link.\n' u'If you have already created Link types in this site, you can migrate ' u'them to Smart Link from the site control panel (Configure Smart Link).' ), type='info')
def install(portal, reinstall=False): setup_tool = portal.portal_setup setup_tool.runAllImportStepsFromProfile("profile-redturtle.smartlink:default") if not reinstall: portal.plone_utils.addPortalMessage( _( "install_info", default=u"Starting from now, all Links created in this site will be Smart Link.\n" u"If you have already created Link types in this site, you can migrate " u"them to Smart Link from the site control panel (Configure Smart Link).", ), type="info", )
def action_update(self, action, data): context = self.context putils = getToolByName(context, 'plone_utils') results = getToolByName(context, 'portal_catalog')(object_provides=ISmartLink.__identifier__) cnt = 0 for res in results: cnt+=1 object = res.getObject() object.setRemoteUrl(object.getRemoteUrl()) object.reindexObject() putils.addPortalMessage(_('update_count_message', default=u"${count} elements updated", mapping={'count': cnt})) return
def actionMigrate(self, action, data): if MIGRATION_MODULE: messages = migrateSmartLink(self.context) i = 0 for m in messages: i += 1 IStatusMessage(self.request).addStatusMessage(m, type='info') portal = getToolByName(self.context, 'portal_url').getPortalObject() portal.plone_utils.addPortalMessage( _('sequence_help_message', default=u"$num element(s) migrated", mapping={'num': i})) return self.request.response.redirect(self.context.absolute_url()) else: output = _( u'migration_error_msg', default= u'You need to install "Products.contentmigration" product for perform the task' ) IStatusMessage(self.request).addStatusMessage(output, type='error') return self.request.response.redirect( self.context.absolute_url() + '/@@blob-smartlink-migration')
class MigrateToSmartLink(formbase.PageForm): form_fields = form.FormFields(IMigrateBlobsSchema) label = _(u'Migrate ATLink to Smart Link') description = _(u'Migrate basic Plone ATLink to Smart Link') @form.action(_(u'Migrate')) def actionMigrate(self, action, data): output = migrateLinkToSmartLink(self.context) cnt = 0 for l in output: cnt += 1 IStatusMessage(self.request).addStatusMessage(l, type='info') IStatusMessage(self.request).addStatusMessage(_( 'update_count_message', default="${count} elements updated", mapping={'count': cnt}), type='info') return self.request.response.redirect(self.context.absolute_url() + '/@@smartlink-config') @form.action(_(u'Cancel')) def actionCancel(self, action, data): return self.request.response.redirect(self.context.absolute_url() + '/@@smartlink-config')
def uninstall(portal, reinstall=False): setup_tool = portal.portal_setup setup_tool.runAllImportStepsFromProfile( 'profile-redturtle.smartlink:uninstall') if getFSVersionTuple()[0] >= 4: unregisterIcon(portal) if not reinstall: removeSmartLinkMarks(portal) setup_tool.runAllImportStepsFromProfile( 'profile-redturtle.smartlink:smartLinkToATLink') logger.info("...done. Thanks you for using me!") portal.plone_utils.addPortalMessage(_( 'uninstall_info', default= u'All of yours Smart Link contents has been transformed back to Plone ATLink' ), type='info')
def action_update(self, action, data): context = self.context putils = getToolByName(context, 'plone_utils') results = getToolByName( context, 'portal_catalog')(object_provides=ISmartLink.__identifier__) cnt = 0 for res in results: cnt += 1 object = res.getObject() object.setRemoteUrl(object.getRemoteUrl()) object.reindexObject() putils.addPortalMessage( _('update_count_message', default=u"${count} elements updated", mapping={'count': cnt})) return
def atLinkToSmartLink(context): portal = context.getSite() if context.readDataFile('redturtle.smartlink_linkToSmartLink.txt') is None: return try: from redturtle.smartlink.migrator import migrateLinkToSmartLink logger.info("Starting migration of ATLink to Smart Link") messages = migrateLinkToSmartLink(portal) i = 0 for m in messages: i+=1 logger.info(m) portal.plone_utils.addPortalMessage(m, type="warning") portal.plone_utils.addPortalMessage(_('sequence_help_message', default=u"$num element(s) migrated", mapping={'num': i})) logger.info("Done") except ImportError: logger.error("Can't do anything. Check if Products.contentmigration is installed")
def otherFilledIfSelected(smartlink): if len(smartlink.frontendlink) != len(smartlink.backendlink): raise Invalid(_(u"Front-end link must correspond to a single back-end link"))
from redturtle.smartlink.interfaces.utility import ISmartlinkConfig from zope import interface from zope.component import getUtility, queryUtility try: from archetypes.referencebrowserwidget import ReferenceBrowserWidget except ImportError: from Products.ATReferenceBrowserWidget.ATReferenceBrowserWidget import ReferenceBrowserWidget LinkSchema = ATLinkSchema.copy() + atapi.Schema(( # HIDDEN! atapi.StringField('remoteUrl', searchable=True, widget=atapi.StringWidget( description='', label=_(u'label_url', default=u'URL'), visible={ 'view': 'invisible', 'edit': 'invisible' }, )), atapi.StringField( "externalLink", searchable=True, required=False, widget=atapi.StringWidget( label=_(u'label_smartlink_externallink', default='External link'), description=_( u'help_smartlink_externallink', default= u"Enter the web address for a page which is not located on this server."
def otherFilledIfSelected(smartlink): if len(smartlink.frontendlink) != len(smartlink.backendlink): raise Invalid( _(u"Front-end link must correspond to a single back-end link"))
class ISmartlinkConfig(Interface): relativelink = schema.Bool( title=_(u"Relative links"), description=_( u'help_relativelink', default= (u'If selected, all internal links in the site will store URLs relative to the portal root, ' u'rather than absolute save the complete absolute ones. ' u'For example: no "http://myhost/plone/foo" but "/plone/foo"')), required=False) frontend_main_link = schema.TextLine( title=_(u"Front-end main URL"), description=_( u'help_frontend_main_link', default= (u'Put there the site main URL you want to expone to visitors. ' u'All Smart Link that starts with the current URL of the portal ' u'will be transformed to use this URL.')), default=u'', required=False) backendlink = schema.List( title=_(u"Back-end URLs"), description=_( u'help_backendlink', default= (u'Put there all your possible back-office URLs you want to transform. ' u'URLs there must be unique')), value_type=schema.TextLine(), default=[], unique=True, required=False) frontendlink = schema.List( title=_(u"Front-end URLs"), description=_( u'help_frontendlink', default= u'Fill there URLs in which you want to change the relative back-end ones.' ), value_type=schema.TextLine(), default=[], unique=False, required=False) proxy_enabled = schema.Bool( title=_(u"Globally enable proxy feature for title and description"), description= _(u'help_enable_proxy_feature', default= u"Disable this if you don't want to use the \"Use referenced content's data\" feature.\n" u"Please note: changing this configuration will not update existings links automatically." ), default=False) @invariant def otherFilledIfSelected(smartlink): if len(smartlink.frontendlink) != len(smartlink.backendlink): raise Invalid( _(u"Front-end link must correspond to a single back-end link"))
class SmartlinkConfigForm(ControlPanelForm): """Smartlink Control Panel Form""" implements(ISmartLinkControlPanelForm) template = ViewPageTemplateFile('controlpanel.pt') form_fields = form.Fields(ISmartlinkConfig) label = _(u"Smart Link configuration") description = _( u'setting_description', default= (u'Fill this configuration panel for production settings; ' u'choose if use relative paths, an unified front-end URL, or manually ' u'enter many back-end/front-end URL (for advanced installation).\n' u'Every configuration option take precedence on the one that follows.\n' u'After changes you (probably) want to run the "Update existing links" task.' )) form_name = _(u"Settings") @property def blob_installed(self): return BLOB @property def contentmigration_installed(self): return MIGRATION def saveFields(self, action, data): CheckAuthenticator(self.request) if form.applyChanges(self.context, self.form_fields, data, self.adapters): self.status = _(u"Changes saved.") self._on_save(data) else: self.status = _(u"No changes made.") @form.action(_(u'label_save_links', default=u'Save'), name=u'save') def handle_edit_action(self, action, data): self.saveFields(action, data) @form.action(_(u'label_cancel_links', default=u'Cancel'), validator=null_validator, name=u'cancel') def handle_cancel_action(self, action, data): IStatusMessage(self.request).addStatusMessage(_("Changes canceled."), type="info") url = getMultiAdapter((self.context, self.request), name='absolute_url')() self.request.response.redirect(url + '/@@smartlink-config') return '' @form.action(_(u'label_update_links', default=u'Update existing links'), name=u'update_links') def action_update(self, action, data): context = self.context putils = getToolByName(context, 'plone_utils') results = getToolByName( context, 'portal_catalog')(object_provides=ISmartLink.__identifier__) cnt = 0 for res in results: cnt += 1 object = res.getObject() object.setRemoteUrl(object.getRemoteUrl()) object.reindexObject() putils.addPortalMessage( _('update_count_message', default=u"${count} elements updated", mapping={'count': cnt})) return