Beispiel #1
0
    def __call__(self):
        """ Perform the update seo properties and redirect if necessary,
            or render the page Call method.
        """
        context = aq_inner(self.context)
        request = self.request
        form = self.request.form
        submitted = form.get('form.submitted', False)
        if submitted:
            msgtype = "info"
            save = form.get('form.button.Save', False)
            if save:
                msg = self.manageSEOProps(**form)
                if not msg:
                    msg = _('seoproperties_saved',
                            default=u'Content SEO properties have been saved.')
                    kwargs = {'modification_date': DateTime()}
                    context.plone_utils.contentEdit(context, **kwargs)
                else:
                    msgtype = "error"
            else:
                # Cancel
                msg = _('seoproperties_canceled', default=u'No content SEO '
                        'properties have been changed.')

            context.plone_utils.addPortalMessage(msg, msgtype)
            if msgtype == "info":
                return request.response.redirect(self.context.absolute_url())

        return self.template()
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)
Beispiel #3
0
 def validateKeywords(self):
     """ see interface """
     text = self.request.get('text')
     ts = getToolByName(self.context, 'translation_service')
     transforms = getUtility(IPortalTransformsTool)
     portal = getToolByName(self.context, 'portal_url').getPortalObject()
     isExternal = queryAdapter(portal, ISEOConfigletSchema).external_keywords_test
     # extract keywords from text
     enc = getSiteEncoding(self.context)
     if text.lower().strip():
         keywords = filter(None, map(lambda x: safe_unicode(x.strip(), enc),
                                      text.lower().strip().split('\n')))
     else:
         return ts.utranslate(domain='quintagroup.seoptimizer',
                              msgid=_(u'Keywords list is empty!'),
                              context=self.context)
     # Get html page internally or with external request
     error_url = ""
     if isExternal:
         # Not pass timeout option because:
         # 1. its value get from the global default timeout settings.
         # 2. timeout option added in python 2.6 (so acceptable only in plone4+)
         try:
             resp = urllib2.urlopen(self.context.absolute_url())
             try:
                 html = resp.read()
             finally:
                 resp.close()
         except (urllib2.URLError, urllib2.HTTPError), e:
             # In case of exceed timeout period or other URL connection errors.
             # Get nearest to context error_log object (stolen from Zope2/App/startup.py)
             html = None
             info = sys.exc_info()
             elog = getToolByName(self.context, "error_log")
             error_url = elog.raising(info)
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 = _("")
Beispiel #5
0
    def validateKeywords(self, text):
        """ see interface """
        ts = getToolByName(self.context, 'translation_service')
        # extract keywords from text
        if text.lower().strip():
            keywords = map(lambda x: x.strip(), text.lower().strip().split('\n'))
        else:
            return ts.utranslate(domain='quintagroup.seoptimizer', msgid=_(u'Keywords list is empty!'), context=self.context)
        # request html page of context object
        url = '%s?without_metatag_keywords=1' % self.context.absolute_url()

        # extract words from url page using lynx browser (test page by 'url' randered without metatag keywords)
        page_text = commands.getoutput('lynx --dump --nolist %s' % url).lower()
        if page_text and page_text != 'sh: lynx: command not found':
            page_text = page_text.decode('utf8')
        else:
            return ts.utranslate(domain='quintagroup.seoptimizer', msgid=_(u'Could not find lynx browser!'), context=self.context)

        # check every keyword on appearing in body of html page
        missing = []
        finding = []
        added = {}
        finded = {}
        for keyword in keywords:
            keyword = keyword.decode('utf8')
            if keyword:
                keyword_on_page =  len(re.findall(u'\\b%s\\b' % keyword, page_text, re.I|re.U))
                if keyword not in added.keys() and not keyword_on_page:
                    missing.append(keyword+u' - 0')
                    added[keyword] = 1
                if keyword not in finded.keys() and keyword_on_page:
                    finding.append(keyword+u' - '+repr(keyword_on_page))
                    finded[keyword] = 1
        # return list of missing and fount keywords
        if missing or finding:
            msg = ts.utranslate(domain='quintagroup.seoptimizer', msgid=_(u'number_keywords'),
                                default=u'Number of keywords at page:\n${found}\n${missing}',
                                mapping={'missing':'\n'.join(missing), 'found': '\n'.join(finding)},
                                context=self.context)
        else:
            msg = ''
        return msg
Beispiel #6
0
 def validateSEOProperty(self, property, value):
     """ Validate a seo property.
     """
     purl = getToolByName(self.context, 'portal_url')()
     state = ''
     if property == PROP_PREFIX+'canonical':
         # validate seo canonical url property
         pdomain = self.getMainDomain(purl)
         if not pdomain == self.getMainDomain(value):
             state = _('canonical_msg', default=u'Canonical URL mast be in ${pdomain} domain.', mapping={'pdomain': pdomain})
     return state
Beispiel #7
0
    def validateKeywords(self):
        """ see interface """
        text = self.request.get('text')
        ts = getToolByName(self.context, 'translation_service')
        # extract keywords from text
        enc = getSiteEncoding(self.context)
        if text.lower().strip():
            keywords = filter(None, map(lambda x: safe_unicode(x.strip(), enc),
                                         text.lower().strip().split('\n')))
        else:
            return ts.utranslate(domain='quintagroup.seoptimizer',
                                 msgid=_(u'Keywords list is empty!'),
                                 context=self.context)
        # request html page of context object
        url = '%s?without_metatag_keywords=1' % self.context.absolute_url()

        # extract words from url page using lynx browser (test page by 'url'
        # randered without metatag keywords)
        page_text = commands.getoutput('lynx --dump --nolist %s' % url).lower()
        if page_text and page_text != 'sh: lynx: command not found':
            page_text = safe_unicode(page_text, 'utf-8')
        else:
            return ts.utranslate(domain='quintagroup.seoptimizer',
                                 msgid=_(u'Could not find lynx browser!'),
                                 context=self.context)

        # check every keyword on appearing in body of html page
        result = []
        for keyword in keywords:
            keyword_on_page = unicode(len(re.findall(u'\\b%s\\b' % keyword, page_text, re.I|re.U)))
            result.append(' - '.join((keyword, keyword_on_page)))
        return ts.utranslate(domain='quintagroup.seoptimizer',
                             msgid=_(u'number_keywords',
                               default=u'Number of keywords at page:\n${result}',
                               mapping={'result':'\n'.join(result)}),
                             context=self.context)
Beispiel #8
0
 def __call__( self ):
     """ Perform the update seo properties and redirect if necessary, or render the page Call method.
     """
     context = aq_inner(self.context)
     request = self.request
     form = self.request.form
     submitted = form.get('form.submitted', False)
     if submitted:
         state = self.manageSEOProps(**form)
         if not state:
             state = _('seoproperties_saved', default=u'Content SEO properties have been saved.')
             context.plone_utils.addPortalMessage(state)
             kwargs = {'modification_date' : DateTime()} 
             context.plone_utils.contentEdit(context, **kwargs) 
             return request.response.redirect(self.context.absolute_url())
         context.plone_utils.addPortalMessage(state, 'error')
     return self.template()
class ISEOConfigletBaseSchema(Interface):

    exposeDCMetaTags = Bool(
        title=_("label_exposeDCMetaTags",
                default='Expose <abbr title="Dublin Core">DC</abbr> '
                'meta tags'),
        description=_("description_seo_dc_metatags",
                      default='Controls if <abbr title="Dublin Core">DC</abbr>'
                      ' 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)
            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'
Beispiel #11
0
        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
Beispiel #12
0
                finally:
                    resp.close()
            except (urllib2.URLError, urllib2.HTTPError), e:
                # In case of exceed timeout period or other URL connection errors.
                # Get nearest to context error_log object (stolen from Zope2/App/startup.py)
                html = None
                info = sys.exc_info()
                elog = getToolByName(self.context, "error_log")
                error_url = elog.raising(info)
        else:
            html = unicode(self.context()).encode(enc)

        # If no html - information about problem with page retrieval should be returned
        result = []
        if html is None:
            result.append("Problem with page retrieval.")
            if error_url:
                result.append("Details at %s." % error_url)
        else:
            page_text = transforms.convert("html_to_text", html).getData()
            # check every keyword on appearing in body of html page
            for keyword in keywords:
                keyword_on_page = unicode(len(re.findall(u'\\b%s\\b' % keyword, page_text, re.I|re.U)))
                result.append(' - '.join((keyword, keyword_on_page)))

        return ts.utranslate(domain='quintagroup.seoptimizer',
                             msgid=_(u'number_keywords',
                               default=u'Number of keywords at page:\n${result}',
                               mapping={'result':'\n'.join(result)}),
                             context=self.context)
        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"
    def validateKeywords(self):
        """ see interface """
        text = self.request.get('text')
        ts = getToolByName(self.context, 'translation_service')
        transforms = getUtility(IPortalTransformsTool)
        portal = getToolByName(self.context, 'portal_url').getPortalObject()
        query_adapter = queryAdapter(portal, ISEOConfigletSchema)
        isExternal = query_adapter.external_keywords_test
        # extract keywords from text
        enc = getSiteEncoding(self.context)
        if text.lower().strip():
            keywords = filter(None, map(lambda x: safe_unicode(x.strip(), enc),
                              text.lower().strip().split('\n')))
        else:
            return ts.utranslate(domain='quintagroup.seoptimizer',
                                 msgid=_(u'Keywords list is empty!'),
                                 context=self.context)
        # Get html page internally or with external request
        error_url = ""
        if isExternal:
            # Not pass timeout option because:
            # 1. its value get from the global default timeout settings.
            # 2. timeout option added in python 2.6
            #    (so acceptable only in plone4+)
            try:
                resp = urllib2.urlopen(self.context.absolute_url())
                try:
                    html = resp.read()
                finally:
                    resp.close()
            except (urllib2.URLError, urllib2.HTTPError):
                # In case of exceed timeout period or
                # other URL connection errors.
                # Get nearest to context error_log object
                # (stolen from Zope2/App/startup.py)
                html = None
                info = sys.exc_info()
                elog = getToolByName(self.context, "error_log")
                error_url = elog.raising(info)
        else:
            html = unicode(self.context()).encode(enc)

        # If no html - information about problem with page retrieval
        # should be returned
        result = []
        if html is None:
            result.append("Problem with page retrieval.")
            if error_url:
                result.append("Details at %s." % error_url)
        else:
            page_text = transforms.convert("html_to_text", html).getData()
            # check every keyword on appearing in body of html page
            for keyword in keywords:
                keyword_on_page = unicode(len(re.findall(u'\\b%s\\b' % keyword,
                                              page_text, re.I | re.U)))
                result.append(' - '.join((keyword, keyword_on_page)))

        return ts.utranslate(domain='quintagroup.seoptimizer',
                             msgid=_(u'number_keywords',
                                     default=u'Number of keywords at page:\n'
                                     '${result}',
                                     mapping={'result': '\n'.join(result)}),
                             context=self.context)
Beispiel #15
0
    def validateKeywords(self):
        """ see interface """
        text = self.request.get('text')
        ts = getToolByName(self.context, 'translation_service')
        transforms = getUtility(IPortalTransformsTool)
        portal = getToolByName(self.context, 'portal_url').getPortalObject()
        query_adapter = queryAdapter(portal, ISEOConfigletSchema)
        isExternal = query_adapter.external_keywords_test
        # extract keywords from text
        enc = getSiteEncoding(self.context)
        if text.lower().strip():
            keywords = filter(
                None,
                map(lambda x: safe_unicode(x.strip(), enc),
                    text.lower().strip().split('\n')))
        else:
            return ts.utranslate(domain='quintagroup.seoptimizer',
                                 msgid=_(u'Keywords list is empty!'),
                                 context=self.context)
        # Get html page internally or with external request
        error_url = ""
        if isExternal:
            # Not pass timeout option because:
            # 1. its value get from the global default timeout settings.
            # 2. timeout option added in python 2.6
            #    (so acceptable only in plone4+)
            try:
                resp = urllib2.urlopen(self.context.absolute_url())
                try:
                    html = resp.read()
                finally:
                    resp.close()
            except (urllib2.URLError, urllib2.HTTPError):
                # In case of exceed timeout period or
                # other URL connection errors.
                # Get nearest to context error_log object
                # (stolen from Zope2/App/startup.py)
                html = None
                info = sys.exc_info()
                elog = getToolByName(self.context, "error_log")
                error_url = elog.raising(info)
        else:
            html = unicode(self.context()).encode(enc)

        # If no html - information about problem with page retrieval
        # should be returned
        result = []
        if html is None:
            result.append("Problem with page retrieval.")
            if error_url:
                result.append("Details at %s." % error_url)
        else:
            page_text = transforms.convert("html_to_text", html).getData()
            # check every keyword on appearing in body of html page
            for keyword in keywords:
                keyword_on_page = unicode(
                    len(
                        re.findall(u'\\b%s\\b' % keyword, page_text,
                                   re.I | re.U)))
                result.append(' - '.join((keyword, keyword_on_page)))

        return ts.utranslate(domain='quintagroup.seoptimizer',
                             msgid=_(u'number_keywords',
                                     default=u'Number of keywords at page:\n'
                                     '${result}',
                                     mapping={'result': '\n'.join(result)}),
                             context=self.context)