import re from zope.interface import Interface from zope.interface import implements from zope.component import adapts from zope.schema import Bool, Choice, Tuple, List from zope.schema import SourceText # BBB Support different versions of Plone getSite = None try: # Plone 3.x, 4.0, 4.1, 4.2 from zope.app.component import hooks getSite = hooks.getSite except ImportError: # Plone 4.3 from zope.component.hooks import getSite from zope.app.form.browser import TextAreaWidget from plone.fieldsets.fieldsets import FormFieldsets from plone.app.controlpanel.form import ControlPanelForm from plone.app.controlpanel.widgets import MultiCheckBoxThreeColumnWidget from Products.CMFCore.utils import getToolByName from Products.CMFPlone.utils import safe_unicode from Products.CMFDefault.formlib.schema import ProxyFieldProperty from Products.CMFDefault.formlib.schema import SchemaAdapterBase from Products.CMFPlone.interfaces import IPloneSiteRoot from quintagroup.seoptimizer import SeoptimizerMessageFactory as _ # Configlet schemas class ISEOConfigletBaseSchema(Interface): exposeDCMetaTags = Bool( title=_("label_exposeDCMetaTags", default='Expose DC ' 'meta tags'), description=_("description_seo_dc_metatags", default='Controls if DC' ' metatags are exposed to page header. They include ' 'DC.description, DC.type, DC.format, DC.creator and ' 'others.'), default=True, required=False) metatags_order = List( title=_("label_metatags_order", default='Meta tags order in the page.'), description=_("help_metatags_order", default='Fill in meta tags (one per line) in the order ' 'in which they will appear on site source pages. ' 'Example: "metaname accessor".'), required=False) types_seo_enabled = Tuple( title=_("label_content_type_title", default='Content Types'), description=_("description_seo_content_types", default='Select content types that will have SEO ' 'properties enabled.'), required=False, missing_value=tuple(), value_type=Choice( vocabulary="plone.app.vocabularies.ReallyUserFriendlyTypes")) default_custom_metatags = List( title=_("label_default_custom_metatags", default='Default custom metatags.'), description=_("help_default_custom_metatags", default='Fill in custom metatag names (one per line) ' 'which will appear on qseo_properties edit tab. ' 'Example: "metaname|metacontent" or "metaname".'), required=False) class ISEOConfigletAdvancedSchema(Interface): custom_script = SourceText( title=_("label_custom_script", default=u'Header JavaScript'), description=_("help_custom_script", default=u"This JavaScript code will be included in " "the rendered HTML as entered in the page header."), default=u'', required=False) fields = List( title=_("label_fields", default='Fields for keywords statistic ' 'calculation.'), description=_("help_fields", default='Fill in filds (one per line)' 'which statistics of keywords usage should ' 'be calculated for.'), required=False) stop_words = List( title=_("label_stop_words", default='Stop words.'), description=_("help_stop_words", default='Fill in stop words ' '(one per line) which will be excluded from kewords ' 'statistics calculation.'), required=False) external_keywords_test = Bool( title=_("label_external_keywords_test", default='External keywords check'), description=_("description_external_keywords_test", default='Make keywords test by opening context url as ' 'external resource with urllib2.openurl(). This is ' 'useful when xdv/Deliverance transformation is used ' 'on the site.'), default=False, required=False) class ISEOConfigletSchema(ISEOConfigletBaseSchema, ISEOConfigletAdvancedSchema): """Combined schema for the adapter lookup. """ class SEOConfigletAdapter(SchemaAdapterBase): adapts(IPloneSiteRoot) implements(ISEOConfigletSchema) def __init__(self, context): super(SEOConfigletAdapter, self).__init__(context) self.portal = getSite() pprop = getToolByName(self.portal, 'portal_properties') self.context = pprop.seo_properties self.siteprops = pprop.site_properties self.ttool = getToolByName(context, 'portal_types') self.encoding = pprop.site_properties.default_charset def getExposeDC(self): return self.siteprops.getProperty('exposeDCMetaTags') def setExposeDC(self, value): return self.siteprops._updateProperty('exposeDCMetaTags', bool(value)) def getTypesSEOEnabled(self): ct_with_seo = self.context.content_types_with_seoproperties return [t for t in self.ttool.listContentTypes() if t in ct_with_seo] def setTypesSEOEnabled(self, value): value = [t for t in self.ttool.listContentTypes() if t in value] self.context._updateProperty('content_types_with_seoproperties', value) def getCustomScript(self): description = getattr(self.context, 'custom_script', u'') return safe_unicode(description) def setCustomScript(self, value): if value is not None: self.context.custom_script = value.encode(self.encoding) else: self.context.custom_script = '' exposeDCMetaTags = property(getExposeDC, setExposeDC) seo_default_custom_metatag = ISEOConfigletSchema['default_custom_metatags'] default_custom_metatags = ProxyFieldProperty(seo_default_custom_metatag) metatags_order = ProxyFieldProperty(ISEOConfigletSchema['metatags_order']) types_seo_enabled = property(getTypesSEOEnabled, setTypesSEOEnabled) custom_script = property(getCustomScript, setCustomScript) fields = ProxyFieldProperty(ISEOConfigletSchema['fields']) stop_words = ProxyFieldProperty(ISEOConfigletSchema['stop_words']) seo_external_keywords_test = ISEOConfigletSchema['external_keywords_test'] external_keywords_test = ProxyFieldProperty(seo_external_keywords_test) class Text2ListWidget(TextAreaWidget): height = 5 splitter = re.compile(u'\\r?\\n', re.S | re.U) def _toFieldValue(self, input): if input == self._missing: return self.context._type() else: return self.context._type(filter(None, self.splitter.split(input))) def _toFormValue(self, value): if value == self.context.missing_value or \ value == self.context._type(): return self._missing else: return u'\r\n'.join(list(value)) # Fieldset configurations baseset = FormFieldsets(ISEOConfigletBaseSchema) baseset.id = 'seobase' baseset.label = _(u'label_seobase', default=u'Base') advancedset = FormFieldsets(ISEOConfigletAdvancedSchema) advancedset.id = 'seoadvanced' advancedset.label = _(u'label_seoadvanced', default=u'Advanced') class SEOConfiglet(ControlPanelForm): form_fields = FormFieldsets(baseset, advancedset) type_seo_enabled = MultiCheckBoxThreeColumnWidget form_fields['default_custom_metatags'].custom_widget = Text2ListWidget form_fields['metatags_order'].custom_widget = Text2ListWidget form_fields['types_seo_enabled'].custom_widget = type_seo_enabled form_fields['types_seo_enabled'].custom_widget.cssClass = 'label' form_fields['fields'].custom_widget = Text2ListWidget form_fields['stop_words'].custom_widget = Text2ListWidget label = _("Search Engine Optimizer configuration") description = _("seo_configlet_description", default="You can select what " "content types are qSEOptimizer-enabled, and control if " "Dublin Core metatags are exposed in the header of content" " pages.") form_name = _("")