Changeset 1313 in products


Ignore:
Timestamp:
Sep 18, 2009 5:29:41 PM (15 years ago)
Author:
liebster
Message:

Added metatags order feature, which is managed by metatags_order property of of configlet

Location:
quintagroup.seoptimizer/trunk
Files:
1 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • quintagroup.seoptimizer/trunk/docs/HISTORY.txt

    r1308 r1313  
    22========= 
    33 
    4 2.0.10 (unreleased) 
     42.1.0 (unreleased) 
    55------------------ 
     6 
     7- Added metatags order feature, which is managed 
     8  by metatags_order property of of configlet 
     9  [liebster] 
    610 
    711- Resolved metatags duplication 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/__init__.py

    r1312 r1313  
    11from AccessControl import allow_module 
    2 from util import SortedDict 
     2from zope.component import queryMultiAdapter 
     3 
    34from Acquisition import aq_inner 
    45from DateTime import DateTime 
    56 
    67from Products.CMFCore.utils import getToolByName 
     8 
     9from quintagroup.seoptimizer.interfaces import IKeywords, IMappingMetaTags 
     10from quintagroup.seoptimizer.util import SortedDict 
    711 
    812allow_module('quintagroup.seoptimizer.util') 
     
    1822 
    1923 
    20  
    2124if _present: 
    2225    old_lmt = PloneTool.listMetaTags 
     
    2528        """Lists meta tags helper. 
    2629 
    27         Creates a mapping of meta tags -> values for the listMetaTags script. 
     30        Creates a mapping of meta tags. 
    2831        """ 
    29         result = {} 
     32 
     33        from quintagroup.seoptimizer.browser.interfaces import IPloneSEOLayer 
     34        if not IPloneSEOLayer.providedBy(self.REQUEST): 
     35            return old_lmt(getToolByName(self, 'plone_utils'), context) 
     36 
     37        result = SortedDict() 
    3038        site_props = getToolByName(self, 'portal_properties').site_properties 
    3139        use_all = site_props.getProperty('exposeDCMetaTags', None) 
    3240 
     41        seo_context = queryMultiAdapter((context, self.REQUEST), name='seo_context') 
     42        adapter = IMappingMetaTags(context, None) 
     43        mapping_metadata = adapter and adapter.getMappingMetaTags() or SortedDict() 
     44 
    3345        if not use_all: 
    34             metadata_names = {'Description': METADATA_DCNAME['Description']} 
     46            metadata_names = mapping_metadata.has_key('DC.description') and {'DC.description': mapping_metadata['DC.description']} or SortedDict() 
     47            if mapping_metadata.has_key('description'): 
     48                metadata_names['description'] = mapping_metadata['description'] 
    3549        else: 
    36             metadata_names = METADATA_DCNAME 
     50            metadata_names = mapping_metadata 
    3751 
    38         for accessor, key in metadata_names.items(): 
    39             method = getattr(aq_inner(context).aq_explicit, accessor, None) 
     52        for key, accessor in metadata_names.items(): 
     53            if accessor == 'seo_keywords': 
     54                # Set the additional matching keywords, if any 
     55                adapter = IKeywords(context, None) 
     56                if adapter is not None: 
     57                    keywords = adapter.listKeywords() 
     58                    if keywords: 
     59                        result['keywords'] = keywords 
     60                continue 
     61 
     62            method = getattr(seo_context, accessor, None) 
     63            if method is None: 
     64                method = getattr(aq_inner(context).aq_explicit, accessor, None) 
     65 
    4066            if not callable(method): 
    4167                continue 
     
    5783                value = ', '.join(value) 
    5884 
    59 #          Exclusion meta tag description and keywords 
    60 #            # Special cases 
    61 #            if accessor == 'Description': 
    62 #                result['description'] = value 
    63 #            elif accessor == 'Subject': 
    64 #                result['keywords'] = value 
     85            # Special cases 
     86            if accessor == 'Description' and not (result.has_key('description') or metadata_names.has_key('description')): 
     87                result['description'] = value 
     88            elif accessor == 'Subject' and not (result.has_key('keywords') or metadata_names.has_key('keywords')): 
     89                result['keywords'] = value 
    6590 
    66             if use_all: 
     91            if accessor not in ('Description', 'Subject'): 
    6792                result[key] = value 
    6893 
     
    104129                result['DC.date.valid_range'] = '%s - %s' % (eff_str, exp_str) 
    105130 
     131        # add custom meta tags (added from qseo tab by user) for given context and default from configlet 
     132        custom_meta_tags = seo_context and seo_context.seo_customMetaTags() or [] 
     133        for tag in custom_meta_tags: 
     134            if tag['meta_content']: 
     135                result[tag['meta_name']] = tag['meta_content'] 
     136 
    106137        return result 
    107138 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/adapters.py

    r408 r1313  
    33from zope.component import queryMultiAdapter 
    44from Products.CMFCore.utils import getToolByName 
    5 from quintagroup.seoptimizer.interfaces import IKeywords 
     5 
     6from quintagroup.seoptimizer.interfaces import IKeywords, IMappingMetaTags 
     7from quintagroup.seoptimizer.util import SortedDict 
    68 
    79 
     
    1416    def listKeywords(self): 
    1517        portal_props = getToolByName(self.context, 'portal_properties') 
    16         seo_props = getToolByName(portal_props, 'seo_properties') 
     18        seo_props = getToolByName(portal_props, 'seo_properties', None) 
    1719 
    1820        # now set type is not using because of it unordered behaviour 
     
    2426        request = self.context.REQUEST 
    2527        seo_context = queryMultiAdapter((self.context, request), name='seo_context') 
    26         keywords = list(seo_context.seo_keywords()) 
    27         lower_keywords = map(lambda x: x.lower(), keywords) 
    28         additional = seo_props.additional_keywords 
     28        if seo_context: 
     29            keywords = list(seo_context.seo_keywords()) 
     30            lower_keywords = map(lambda x: x.lower(), keywords) 
     31            additional = seo_props.additional_keywords 
    2932 
    30         is_test = self.context.REQUEST.get('qseo_without_additional_keywords', None) 
     33            is_test = self.context.REQUEST.get('qseo_without_additional_keywords', None) 
    3134 
    32         if additional and is_test is None: 
    33             # extract words from url page using lynx browser 
    34             text = commands.getoutput('lynx --dump --nolist %s?qseo_without_additional_keywords=1' % self.context.absolute_url()).lower() 
    35             if text and text != 'sh: lynx: command not found': 
    36                 for keyword in additional: 
    37                     if keyword.lower() not in lower_keywords and re.compile(r'\b%s\b' % keyword, re.I).search(text): 
    38                         keywords.append(keyword) 
     35            if additional and is_test is None: 
     36                # extract words from url page using lynx browser 
     37                text = commands.getoutput('lynx --dump --nolist %s?qseo_without_additional_keywords=1' % self.context.absolute_url()).lower() 
     38                if text and text != 'sh: lynx: command not found': 
     39                    for keyword in additional: 
     40                        if keyword.lower() not in lower_keywords and re.compile(r'\b%s\b' % keyword, re.I).search(text): 
     41                            keywords.append(keyword) 
     42            return ', '.join(keywords) 
     43        return '' 
    3944 
    40         return ', '.join(keywords) 
     45 
     46class MappingMetaTags(object): 
     47    implements(IMappingMetaTags) 
     48 
     49    def __init__(self, context): 
     50        self.context = context 
     51        self.portal_props = getToolByName(self.context, 'portal_properties') 
     52        self.seo_props = getToolByName(self.portal_props, 'seo_properties', None) 
     53 
     54    def getMappingMetaTags(self): 
     55        metadata_name = SortedDict() 
     56        if self.seo_props: 
     57            pmn = self.seo_props.getProperty('metatags_order') 
     58            pmn = pmn and pmn or '' 
     59            for mt in [mt.split(' ') for mt in pmn if len(mt.split(' '))==2]: 
     60                metadata_name[mt[0]] = mt[1] 
     61        return metadata_name 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/configure.zcml

    r1308 r1313  
    88        manager="plone.app.layout.viewlets.interfaces.IHtmlHead" 
    99        class=".viewlets.TitleCommentViewlet" 
    10         layer=".interfaces.IPloneSEOLayer" 
    11         permission="zope2.View" 
    12         /> 
    13         
    14     <!--browser:viewlet 
    15         name="quintagroup.seoptimizer.http_equiv" 
    16         manager="plone.app.layout.viewlets.interfaces.IHtmlHead" 
    17         class=".viewlets.HTTPEquiv" 
    18         layer=".interfaces.IPloneSEOLayer" 
    19         permission="zope2.View" 
    20         /--> 
    21  
    22     <!--browser:viewlet 
    23         name="quintagroup.seoptimizer.base" 
    24         manager="plone.app.layout.viewlets.interfaces.IHtmlHead" 
    25         class=".viewlets.BaseUrlViewlet" 
    26         layer=".interfaces.IPloneSEOLayer" 
    27         permission="zope2.View" 
    28         /--> 
    29  
    30     <!--browser:viewlet 
    31         name="quintagroup.seoptimizer.generator" 
    32         manager="plone.app.layout.viewlets.interfaces.IHtmlHead" 
    33         template="templates/generator.pt" 
    34         layer=".interfaces.IPloneSEOLayer" 
    35         permission="zope2.View" 
    36         /--> 
    37  
    38     <browser:viewlet 
    39         name="quintagroup.seoptimizer.metatags" 
    40         manager="plone.app.layout.viewlets.interfaces.IHtmlHead" 
    41         class=".viewlets.MetaTagsViewlet" 
    4210        layer=".interfaces.IPloneSEOLayer" 
    4311        permission="zope2.View" 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/keywords.py

    r387 r1313  
    1616    def validateKeywords(self, text): 
    1717        """ see interface """ 
    18  
    1918        # extract keywords from text 
    2019        if not text.strip(): 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/templates/seo_controlpanel.pt

    r1271 r1313  
    4545                            <textarea cols="60" id="default_custom_metatags" name="default_custom_metatags" rows="15" 
    4646                                      tal:content="python:'\n'.join(view.getDefaultCustomMetatags())"></textarea> 
     47                        </div> 
     48                    </div> 
     49 
     50                    <div class="field"> 
     51                        <label for="metatags_order" i18n:translate="label_metatags_order"> 
     52                            Meta tags order in the page. 
     53                        </label> 
     54                        <div class="formHelp" i18n:translate="help_metatags_order"> 
     55                            Fill in meta tags order (one per line) which will appear on qseo_properties 
     56                            edit tab. Example: "metaname accessor". 
     57                        </div> 
     58                        <div class="widget"> 
     59                            <textarea cols="60" id="metatags_order" name="metatags_order" rows="15" 
     60                                      tal:content="python:'\n'.join(view.getMetaTagsOrder())"></textarea> 
    4761                        </div> 
    4862                    </div> 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/viewlets.py

    r1308 r1313  
    11from cgi import escape 
    22from zope.component import getMultiAdapter 
    3 from zope.viewlet.interfaces import IViewlet 
    43from Products.CMFPlone.utils import safe_unicode 
    54from plone.app.layout.viewlets.common import ViewletBase 
    65from Products.CMFCore.utils import getToolByName 
    7 from AccessControl import Unauthorized 
    8 from quintagroup.seoptimizer.util import SortedDict 
    9 from quintagroup.seoptimizer.interfaces import IKeywords  
     6 
    107 
    118class TitleCommentViewlet(ViewletBase): 
     
    4946                return u"%s\n%s"%(qseo_title, qseo_comments) 
    5047 
    51 #class HTTPEquiv(ViewletBase): 
    52 #     
    53 #    def charset( self ): 
    54 #        context = self.context.aq_inner 
    55 #        site_properties = getToolByName( context, 'portal_properties').site_properties 
    56 #        return site_properties.getProperty('default_charset', 'utf-8') 
    57 #     
    58 #    def render( self ): 
    59 #        return """<meta http-equiv="Content-Type" content="text/html; charset=%s" />"""%self.charset() 
    60 #          
    61 #class BaseUrlViewlet( ViewletBase ): 
    62 #    """ 
    63 #       simpel viewlet for base href rendering 
    64 #    """ 
    65 #    def renderBase( self ): 
    66 #        # returns correct base href 
    67 #        context = self.context.aq_inner 
    68 #        isFolder = getattr(context.aq_explicit, 'isPrincipiaFolderish', 0) 
    69 #        base_url = context.absolute_url() 
    70 # 
    71 #        # when accessing via WEBDAV you're not allowed to access aq_explicit 
    72 #        try: 
    73 #            return isFolder and '%s/'%base_url or base_url 
    74 #        except (Unauthorized, 'Unauthorized'): 
    75 #            pass 
    76 # 
    77 #    def render( self ): 
    78 #        return """<base href="%s" /><!--[if lt IE 7]></base><![endif]-->"""% self.renderBase() 
    79  
    80 class MetaTagsViewlet( ViewletBase ): 
    81  
    82     def listMetaTags( self ): 
    83         context = self.context.aq_inner 
    84         portal_props = getToolByName(context, 'portal_properties') 
    85         pu = getToolByName(context, 'plone_utils') 
    86         seo_props = getToolByName(portal_props, 'seo_properties', None) 
    87         if seo_props is None: 
    88             return pu.listMetaTags(context) 
    89  
    90         site_props = getToolByName(portal_props, 'site_properties') 
    91         exposeDCMetaTags = site_props.exposeDCMetaTags 
    92  
    93         metaTags = SortedDict() 
    94         #metaTags.update(pu.listMetaTags(context)) 
    95         metadataList = [ 
    96             ('seo_description', 'description'), 
    97             ('seo_keywords',    'keywords'), 
    98             ('seo_robots',      'robots'), 
    99             ('seo_distribution','distribution')] 
    100  
    101         if exposeDCMetaTags: 
    102             metadataList.append(('seo_distribution', 'DC.distribution')) 
    103  
    104         seo_context = getMultiAdapter((self.context, self.request), name='seo_context') 
    105         for accessor, key in metadataList: 
    106             method = getattr(seo_context, accessor, None) 
    107             if not callable(method): 
    108                 # ups 
    109                 continue 
    110             # Catch AttributeErrors raised by some AT applications 
    111             try: 
    112                 value = method() 
    113             except AttributeError: 
    114                 value = None 
    115  
    116             if not value: 
    117                 continue 
    118             if isinstance(value, (tuple, list)): 
    119                 value = ', '.join(value) 
    120  
    121             metaTags[key] = value 
    122  
    123         # add custom meta tags (added from qseo tab by user) for given context and default from configlet 
    124         custom_meta_tags = seo_context.seo_customMetaTags() 
    125         for tag in custom_meta_tags: 
    126             if tag['meta_content']: 
    127                 metaTags[tag['meta_name']] = tag['meta_content'] 
    128  
    129         # Set the additional matching keywords, if any 
    130         adapter = IKeywords(context, None) 
    131         if adapter is not None: 
    132             keywords = adapter.listKeywords() 
    133             if keywords: 
    134                 metaTags['keywords'] = keywords 
    135  
    136         return metaTags 
    137  
    138     def render( self ): 
    139         return '\n'.join([safe_unicode("""<meta name="%s" content="%s" />"""%(name, content)) \ 
    140                                        for name, content in self.listMetaTags().items()]) 
    14148 
    14249class CustomScriptViewlet( ViewletBase ): 
     
    14855        if seo_props is None: 
    14956            return ''  
    150         return seo_props.getProperty('custom_script', '') 
     57        return seo_props.getProperty('custom_script', '') 
    15158 
    15259    def render( self ): 
     
    16269        seo_context = getMultiAdapter((self.context, self.request), name='seo_context') 
    16370        return """<link rel="canonical" href="%s" />""" % seo_context.seo_canonical() 
    164  
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/views.py

    r1309 r1313  
    217217        sp = self.portal_properties.site_properties 
    218218        return sp.getProperty('exposeDCMetaTags') 
    219      
     219 
    220220    def getDefaultCustomMetatags( self ): 
    221221        """ 
     
    223223        seo = self.portal_properties.seo_properties 
    224224        return seo.getProperty('default_custom_metatags') 
     225 
     226    def getMetaTagsOrder( self ): 
     227        """ 
     228        """ 
     229        seo = self.portal_properties.seo_properties 
     230        return seo.getProperty('metatags_order') 
    225231 
    226232    def getAdditionalKeywords( self ): 
     
    250256        additionalKeywords=request.get('additionalKeywords', []) 
    251257        default_custom_metatags=request.get('default_custom_metatags', []) 
     258        metatags_order=request.get('metatags_order', []) 
    252259 
    253260        site_props = getToolByName(self.portal_properties, 'site_properties') 
     
    261268            seo_props.manage_changeProperties(additional_keywords=additionalKeywords) 
    262269            seo_props.manage_changeProperties(default_custom_metatags=default_custom_metatags) 
     270            seo_props.manage_changeProperties(metatags_order=metatags_order) 
    263271 
    264272            for ptype in self.portal_types.objectValues(): 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/configure.zcml

    r726 r1313  
    44    xmlns:browser="http://namespaces.zope.org/browser" 
    55    xmlns:genericsetup="http://namespaces.zope.org/genericsetup" 
    6     xmlns:cmf="http://namespaces.zope.org/cmf" 
    7     > 
     6    xmlns:cmf="http://namespaces.zope.org/cmf"> 
    87 
    98  <five:registerPackage package="." /> 
     
    1413      directory="profiles/default" 
    1514      description="Install quintagroup.seoptimizer" 
    16       provides="Products.GenericSetup.interfaces.EXTENSION" /> 
     15      provides="Products.GenericSetup.interfaces.EXTENSION" 
     16      /> 
    1717 
    1818  <genericsetup:registerProfile 
     
    2121      directory="profiles/uninstall" 
    2222      description="Uninstall quintagroup.seoptimizer" 
    23       provides="Products.GenericSetup.interfaces.EXTENSION" /> 
     23      provides="Products.GenericSetup.interfaces.EXTENSION" 
     24      /> 
    2425 
    25     <browser:page 
    26         for="Products.Archetypes.interfaces.IBaseObject" 
    27         attribute="validateKeywords" 
    28         class=".browser.keywords.ValidateSEOKeywordsView" 
    29         name="checkSEOKeywords" 
    30         permission="cmf.ModifyPortalContent" 
    31         /> 
     26  <browser:page 
     27      for="Products.Archetypes.interfaces.IBaseObject" 
     28      attribute="validateKeywords" 
     29      class=".browser.keywords.ValidateSEOKeywordsView" 
     30      name="checkSEOKeywords" 
     31      permission="cmf.ModifyPortalContent" 
     32      /> 
    3233 
    3334  <adapter 
    34     for="Products.Archetypes.public.BaseObject" 
    35     provides=".interfaces.IKeywords" 
    36     factory=".adapters.AdditionalKeywords" 
    37     /> 
     35      for="Products.Archetypes.public.BaseObject" 
     36      provides=".interfaces.IKeywords" 
     37      factory=".adapters.AdditionalKeywords" 
     38      /> 
     39 
     40  <adapter 
     41      for="Products.Archetypes.public.BaseContent" 
     42      provides=".interfaces.IMappingMetaTags" 
     43      factory=".adapters.MappingMetaTags" 
     44      /> 
    3845 
    3946  <cmf:registerDirectory name="quintagroup.seoptimizer" /> 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/interfaces.py

    r387 r1313  
    77        """Returns all the existing keywords for the current content type. 
    88        """ 
     9 
     10class IMappingMetaTags(Interface): 
     11    """ 
     12    """ 
     13    def getMappingMetaTags(): 
     14        """Returns mapping {meta_name:accssesor} all the meta tags. 
     15        """ 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/profiles/default/propertiestool.xml

    r869 r1313  
    6767  <property name="additional_keywords" type="lines"/> 
    6868  <property name="default_custom_metatags" type="lines"/> 
     69  <property name="metatags_order" type="lines"> 
     70   <element value="DC.publisher Publisher"/> 
     71   <element value="DC.description Description"/> 
     72   <element value="DC.contributors Contributors"/> 
     73   <element value="DC.creator Creator"/> 
     74   <element value="DC.format Format"/> 
     75   <element value="DC.rights Rights"/> 
     76   <element value="DC.language Language"/> 
     77   <element value="DC.date.modified ModificationDate"/> 
     78   <element value="DC.date.created CreationDate"/> 
     79   <element value="DC.type Type"/> 
     80   <element value="DC.subject Subject"/> 
     81   <element value="DC.distribution seo_distribution"/> 
     82   <element value="description seo_description"/> 
     83   <element value="keywords seo_keywords"/> 
     84   <element value="robots seo_robots"/> 
     85   <element value="distribution seo_distribution"/> 
     86  </property> 
    6987 </object> 
    7088 <object name="site_properties" meta_type="Plone Property Sheet"> 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/profiles/default/viewlets.xml

    r1308 r1313  
    22<object> 
    33  <order manager="plone.htmlhead" skinname="*"> 
    4     <!--viewlet name="quintagroup.seoptimizer.http_equiv" /--> 
    54    <viewlet name="plone.htmlhead.title" /> 
    6     <!--viewlet name="quintagroup.seoptimizer.base" /--> 
    7     <!--viewlet name="quintagroup.seoptimizer.generator" /--> 
    8     <viewlet name="quintagroup.seoptimizer.metatags" /> 
    9     <viewlet name="quintagroup.seoptimizer.canonicalurl" /> 
    105    <viewlet name="quintagroup.seoptimizer.customscript" /> 
    116    <viewlet name="plone.resourceregistries" /> 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/tests/testQSEOptimizer.py

    r1269 r1313  
    2828                    'meta_content' : ''} 
    2929                  ] 
     30view_metatags = ['DC.creator', 'DC.format', 'DC.date.modified', 'DC.date.created', 'DC.type', 
     31                   'DC.distribution', 'description', 'keywords', 'robots', 'distribution'] 
    3032 
    3133global_custom_metatags = {'default_custom_metatags':'metatag1|global_metatag1value\nmetatag4|global_metatag4value'} 
     
    215217    def testDescription(self): 
    216218        m = re.match('.*<meta name="description" content="it is description" />', self.html, re.S|re.M) 
     219        if not m: 
     220            m = re.match('.*<meta content="it is description" name="description" />', self.html, re.S|re.M) 
    217221        self.assert_(m, 'Description not set in') 
    218222 
    219223    def testKeywords(self): 
    220224        m = re.match('.*<meta name="keywords" content="my1|key2" />', self.html, re.S|re.M) 
     225        if not m: 
     226             m = re.match('.*<meta content="my1|key2" name="keywords" />', self.html, re.S|re.M) 
    221227        self.assert_(m, 'Keywords not set in') 
    222228 
    223229    def testRobots(self): 
    224230        m = re.match('.*<meta name="robots" content="ALL" />', self.html, re.S|re.M) 
     231        if not m: 
     232            m = re.match('.*<meta content="ALL" name="robots" />', self.html, re.S|re.M) 
    225233        self.assert_(m, 'Robots not set in') 
    226234 
    227235    def testDistribution(self): 
    228236        m = re.match('.*<meta name="distribution" content="Global" />', self.html, re.S|re.M) 
     237        if not m: 
     238            m = re.match('.*<meta content="Global" name="distribution" />', self.html, re.S|re.M) 
    229239        self.assert_(m, 'Distribution not set in') 
    230240 
     
    234244 
    235245    def testTagsOrder(self): 
    236         m = re.search('name="description".+name="keywords"', self.html, re.S|re.M) 
     246        mtop = self.sp.getProperty('metatags_order') 
     247        metatags_order = [t.split(' ')[0] for t in mtop if len(t.split(' '))==2 and t.split(' ')[0] in view_metatags] 
     248        m = re.search('.*'.join(['<meta.*name="%s".*/>' %t for t in metatags_order]), self.html, re.S|re.M) 
    237249        self.assert_(m, "Meta tags order not supported.") 
     250 
     251        mtop = list(mtop) 
     252        mtop.reverse() 
     253        metatags_order = [t.split(' ')[0] for t in mtop if len(t.split(' '))==2 and t.split(' ')[0] in view_metatags] 
     254        m = re.search('.*'.join(['<meta.*name="%s".*/>' %t for t in metatags_order]), self.html, re.S|re.M) 
     255        self.assertFalse(m, "Meta tags order not supported.") 
     256 
     257        self.sp.manage_changeProperties(**{'metatags_order':tuple(mtop)}) 
     258        html = self.publish(self.abs_path, self.basic_auth).getBody() 
     259        m = re.search('.*'.join(['<meta.*name="%s".*/>' %t for t in metatags_order]), self.html, re.S|re.M) 
     260        self.assertFalse(m, "Meta tags order not supported.") 
     261 
     262        m = re.search('.*'.join(['<meta.*name="%s".*/>' %t for t in metatags_order]), html, re.S|re.M) 
     263        self.assert_(m, "Meta tags order not supported.") 
     264 
    238265 
    239266    def testCustomMetaTags(self): 
    240267        for tag in custom_metatags: 
    241268            m = re.search('<meta name="%(meta_name)s" content="%(meta_content)s" />' % tag, self.html, re.S|re.M) 
     269            if not m: 
     270                m = re.search('<meta content="%(meta_content)s" name="%(meta_name)s" />' % tag, self.html, re.S|re.M) 
    242271            if tag['meta_content']: 
    243272                self.assert_(m, "Custom meta tag %s not applied." % tag['meta_name']) 
     
    245274                self.assert_(not m, "Meta tag %s has no content, but is present in the page." % tag['meta_name']) 
    246275        m = re.search('<meta name="metatag4" content="global_metatag4value" />' , self.html, re.S|re.M) 
     276        if not m: 
     277            m = re.search('<meta content="global_metatag4value" name="metatag4" />' , self.html, re.S|re.M) 
    247278        self.assert_(m, "Global custom meta tag %s not applied." % 'metatag4') 
    248279 
     
    253284        html = self.publish(self.abs_path, self.basic_auth).getBody() 
    254285        m = re.search('<meta name="metatag4" content="global_metatag4value" />' , html, re.S|re.M) 
     286        if not m: 
     287            m = re.search('<meta content="global_metatag4value" name="metatag4" />' , html, re.S|re.M) 
    255288        self.assert_(not m, "Global custom meta tag %s is prosent in the page." % 'metatag4') 
    256289        m = re.search('<meta name="metatag1" content="global_metatag1value" />' , html, re.S|re.M) 
     290        if not m: 
     291            m = re.search('<meta content="global_metatag1value" name="metatag1" />' , html, re.S|re.M) 
    257292        self.assert_(m, "Global custom meta tag %s is prosent in the page." % 'metatag4') 
    258293 
     
    311346        self.my_doc.manage_addProperty('qSEO_keywords', ('foo',), 'lines') 
    312347        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth)) 
    313         m = re.match('.*<meta\ name="keywords"\ content="foo"\ />', self.html, re.S|re.M) 
     348        m = re.match('.*<meta\ content="foo"\ name="keywords"\ />', self.html, re.S|re.M) 
     349        if not m: 
     350            m = re.match('.*<meta\ name="keywords"\ content="foo"\ />', self.html, re.S|re.M) 
    314351        self.assert_(m, "No 'foo' keyword find") 
    315352 
     
    317354        self.my_doc.manage_addProperty('qSEO_keywords', ('foo', 'bar'), 'lines') 
    318355        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth)) 
    319         m = re.match('.*<meta\ name="keywords"\ content="foo, bar"\ />', self.html, re.S|re.M) 
     356        m = re.match('.*<meta\ content="foo, bar"\ name="keywords"\ />', self.html, re.S|re.M) 
     357        if not m: 
     358            m = re.match('.*<meta\ name="keywords"\ content="foo, bar"\ />', self.html, re.S|re.M) 
    320359        self.assert_(m, "No 'foo, bar' keyword find") 
    321360 
     
    329368        self.sp.additional_keywords = ('foo',) 
    330369        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth)) 
    331         m = re.match('.*<meta\ name="keywords"\ content="foo"\ />', self.html, re.S|re.M) 
     370        m = re.match('.*<meta\ content="foo"\ name="keywords"\ />', self.html, re.S|re.M) 
     371        if not m: 
     372            m = re.match('.*<meta\ name="keywords"\ content="foo"\ />', self.html, re.S|re.M) 
    332373        self.assert_(m, "No 'foo' keyword find") 
    333374 
     
    336377        self.sp.additional_keywords = ('foo', 'bar') 
    337378        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth)) 
    338         m = re.match('.*<meta\ name="keywords"\ content="foo, bar"\ />', self.html, re.S|re.M) 
     379        m = re.match('.*<meta\ content="foo, bar"\ name="keywords"\ />', self.html, re.S|re.M) 
     380        if not m: 
     381            m = re.match('.*<meta\ name="keywords"\ content="foo, bar"\ />', self.html, re.S|re.M) 
    339382        self.assert_(m, "No 'foo, bar' keyword find") 
    340383 
     
    344387        self.my_doc.manage_addProperty('qSEO_keywords', ('baz',), 'lines') 
    345388        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth)) 
    346         m = re.match('.*<meta\ name="keywords"\ content="baz,\ foo,\ bar"\ />', self.html, re.S|re.M) 
     389        m = re.match('.*<meta\ content="baz,\ foo,\ bar"\ name="keywords"\ />', self.html, re.S|re.M) 
     390        if not m: 
     391            m = re.match('.*<meta\ name="keywords"\ content="baz,\ foo,\ bar"\ />', self.html, re.S|re.M) 
    347392        self.assert_(m, "No 'foo, bar, baz' keyword find") 
    348393 
     
    382427        self.my_doc.qseo_properties_edit() 
    383428        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth)) 
    384  
    385         m = re.match('.*<meta content=".*?" name="DC.format" />', self.html, re.S|re.M) or re.match('.*<meta content=".*?" name="DC.distribution" />', self.html, re.S|re.M) 
     429        m1 = re.match('.*<meta\ name="DC.format"\ content=".*?"\ />', self.html, re.S|re.M) 
     430        if not m1: 
     431            m1 = re.match('.*<meta content=".*?" name="DC.format" />', self.html, re.S|re.M) 
     432        m2 = re.match('.*<meta name="DC.distribution" content=".*?" />', self.html, re.S|re.M) 
     433        if not m2: 
     434            m2 = re.match('.*<meta content=".*?" name="DC.distribution" />', self.html, re.S|re.M) 
     435        m = m1 or m2 
    386436        self.assert_(not m, 'DC meta tags avaliable when exposeDCMetaTags=False') 
    387437 
     
    390440        self.my_doc.qseo_properties_edit() 
    391441        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth)) 
    392         m = re.match('.*<meta\ name="DC.format"\ content=".*?"\ />', self.html, re.S|re.M) and re.match('.*<meta\ name="DC.type"\ content=".*?"\ />', self.html, re.S|re.M) 
     442        m1 = re.match('.*<meta\ content=".*?"\ name="DC.format"\ />', self.html, re.S|re.M) 
     443        if not m1: 
     444            m1 = re.match('.*<meta\ name="DC.format"\ content=".*?"\ />', self.html, re.S|re.M) 
     445        m2 = re.match('.*<meta\ content=".*?"\ name="DC.type"\ />', self.html, re.S|re.M) 
     446        if not m2: 
     447            m2 = re.match('.*<meta\ name="DC.type"\ content=".*?"\ />', self.html, re.S|re.M) 
     448        m = m1 and m2 
    393449        self.assert_(m, 'DC meta tags not avaliable when createManager=True') 
    394450 
  • quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/util.py

    r429 r1313  
    1212class SortedDict(dict): 
    1313    security = ClassSecurityInfo() 
    14     security.declarePublic('items')     
     14 
     15    security.declarePublic('items') 
    1516    def items(self): 
    16         primary_metatags = ['description', 'keywords'] 
     17        primary_metatags = self.pmt 
    1718        lst = [(name,self[name]) for name in primary_metatags                    \ 
    1819                                                 if name in self.keys()] +       \ 
     
    2021                                                 if name not in primary_metatags] 
    2122        return lst 
     23 
     24 
     25    security.declarePublic('__init__') 
     26    def __init__(self, *args, **kwargs): 
     27        super(SortedDict,self).__init__(*args, **kwargs) 
     28        self.pmt = [] 
     29 
     30 
     31    security.declarePublic('__setitem__') 
     32    def __setitem__(self, i, y): 
     33        super(SortedDict,self).__setitem__(i, y) 
     34        if i not in self.pmt: 
     35            self.pmt.append(i) 
    2236 
    2337try: 
Note: See TracChangeset for help on using the changeset viewer.