import re from zope.interface import Interface from zope.interface import implements from zope.component import adapts from zope.schema.vocabulary import SimpleTerm from zope.schema.vocabulary import SimpleVocabulary from zope.schema import Bool, Text, Choice, Tuple, List from zope.schema import SourceText from zope.app.form.browser import RadioWidget from zope.formlib.form import FormFields from zope.app.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) 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) default_custom_metatags = ProxyFieldProperty(ISEOConfigletSchema['default_custom_metatags']) 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']) 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) form_fields['default_custom_metatags'].custom_widget = Text2ListWidget form_fields['metatags_order'].custom_widget = Text2ListWidget form_fields['types_seo_enabled'].custom_widget = MultiCheckBoxThreeColumnWidget 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 = _("")