Changeset 1313 in products
- Timestamp:
- Sep 18, 2009 5:29:41 PM (15 years ago)
- Location:
- quintagroup.seoptimizer/trunk
- Files:
-
- 1 deleted
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
quintagroup.seoptimizer/trunk/docs/HISTORY.txt
r1308 r1313 2 2 ========= 3 3 4 2. 0.10 (unreleased)4 2.1.0 (unreleased) 5 5 ------------------ 6 7 - Added metatags order feature, which is managed 8 by metatags_order property of of configlet 9 [liebster] 6 10 7 11 - Resolved metatags duplication -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/__init__.py
r1312 r1313 1 1 from AccessControl import allow_module 2 from util import SortedDict 2 from zope.component import queryMultiAdapter 3 3 4 from Acquisition import aq_inner 4 5 from DateTime import DateTime 5 6 6 7 from Products.CMFCore.utils import getToolByName 8 9 from quintagroup.seoptimizer.interfaces import IKeywords, IMappingMetaTags 10 from quintagroup.seoptimizer.util import SortedDict 7 11 8 12 allow_module('quintagroup.seoptimizer.util') … … 18 22 19 23 20 21 24 if _present: 22 25 old_lmt = PloneTool.listMetaTags … … 25 28 """Lists meta tags helper. 26 29 27 Creates a mapping of meta tags -> values for the listMetaTags script.30 Creates a mapping of meta tags. 28 31 """ 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() 30 38 site_props = getToolByName(self, 'portal_properties').site_properties 31 39 use_all = site_props.getProperty('exposeDCMetaTags', None) 32 40 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 33 45 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'] 35 49 else: 36 metadata_names = METADATA_DCNAME50 metadata_names = mapping_metadata 37 51 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 40 66 if not callable(method): 41 67 continue … … 57 83 value = ', '.join(value) 58 84 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 65 90 66 if use_all:91 if accessor not in ('Description', 'Subject'): 67 92 result[key] = value 68 93 … … 104 129 result['DC.date.valid_range'] = '%s - %s' % (eff_str, exp_str) 105 130 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 106 137 return result 107 138 -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/adapters.py
r408 r1313 3 3 from zope.component import queryMultiAdapter 4 4 from Products.CMFCore.utils import getToolByName 5 from quintagroup.seoptimizer.interfaces import IKeywords 5 6 from quintagroup.seoptimizer.interfaces import IKeywords, IMappingMetaTags 7 from quintagroup.seoptimizer.util import SortedDict 6 8 7 9 … … 14 16 def listKeywords(self): 15 17 portal_props = getToolByName(self.context, 'portal_properties') 16 seo_props = getToolByName(portal_props, 'seo_properties' )18 seo_props = getToolByName(portal_props, 'seo_properties', None) 17 19 18 20 # now set type is not using because of it unordered behaviour … … 24 26 request = self.context.REQUEST 25 27 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 29 32 30 is_test = self.context.REQUEST.get('qseo_without_additional_keywords', None)33 is_test = self.context.REQUEST.get('qseo_without_additional_keywords', None) 31 34 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 '' 39 44 40 return ', '.join(keywords) 45 46 class 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 8 8 manager="plone.app.layout.viewlets.interfaces.IHtmlHead" 9 9 class=".viewlets.TitleCommentViewlet" 10 layer=".interfaces.IPloneSEOLayer"11 permission="zope2.View"12 />13 14 <!--browser:viewlet15 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:viewlet23 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:viewlet31 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:viewlet39 name="quintagroup.seoptimizer.metatags"40 manager="plone.app.layout.viewlets.interfaces.IHtmlHead"41 class=".viewlets.MetaTagsViewlet"42 10 layer=".interfaces.IPloneSEOLayer" 43 11 permission="zope2.View" -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/keywords.py
r387 r1313 16 16 def validateKeywords(self, text): 17 17 """ see interface """ 18 19 18 # extract keywords from text 20 19 if not text.strip(): -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/templates/seo_controlpanel.pt
r1271 r1313 45 45 <textarea cols="60" id="default_custom_metatags" name="default_custom_metatags" rows="15" 46 46 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> 47 61 </div> 48 62 </div> -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/viewlets.py
r1308 r1313 1 1 from cgi import escape 2 2 from zope.component import getMultiAdapter 3 from zope.viewlet.interfaces import IViewlet4 3 from Products.CMFPlone.utils import safe_unicode 5 4 from plone.app.layout.viewlets.common import ViewletBase 6 5 from 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 10 7 11 8 class TitleCommentViewlet(ViewletBase): … … 49 46 return u"%s\n%s"%(qseo_title, qseo_comments) 50 47 51 #class HTTPEquiv(ViewletBase):52 #53 # def charset( self ):54 # context = self.context.aq_inner55 # site_properties = getToolByName( context, 'portal_properties').site_properties56 # 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 rendering64 # """65 # def renderBase( self ):66 # # returns correct base href67 # context = self.context.aq_inner68 # 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_explicit72 # try:73 # return isFolder and '%s/'%base_url or base_url74 # except (Unauthorized, 'Unauthorized'):75 # pass76 #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_inner84 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.exposeDCMetaTags92 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 # ups109 continue110 # Catch AttributeErrors raised by some AT applications111 try:112 value = method()113 except AttributeError:114 value = None115 116 if not value:117 continue118 if isinstance(value, (tuple, list)):119 value = ', '.join(value)120 121 metaTags[key] = value122 123 # add custom meta tags (added from qseo tab by user) for given context and default from configlet124 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 any130 adapter = IKeywords(context, None)131 if adapter is not None:132 keywords = adapter.listKeywords()133 if keywords:134 metaTags['keywords'] = keywords135 136 return metaTags137 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()])141 48 142 49 class CustomScriptViewlet( ViewletBase ): … … 148 55 if seo_props is None: 149 56 return '' 150 57 return seo_props.getProperty('custom_script', '') 151 58 152 59 def render( self ): … … 162 69 seo_context = getMultiAdapter((self.context, self.request), name='seo_context') 163 70 return """<link rel="canonical" href="%s" />""" % seo_context.seo_canonical() 164 -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/views.py
r1309 r1313 217 217 sp = self.portal_properties.site_properties 218 218 return sp.getProperty('exposeDCMetaTags') 219 219 220 220 def getDefaultCustomMetatags( self ): 221 221 """ … … 223 223 seo = self.portal_properties.seo_properties 224 224 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') 225 231 226 232 def getAdditionalKeywords( self ): … … 250 256 additionalKeywords=request.get('additionalKeywords', []) 251 257 default_custom_metatags=request.get('default_custom_metatags', []) 258 metatags_order=request.get('metatags_order', []) 252 259 253 260 site_props = getToolByName(self.portal_properties, 'site_properties') … … 261 268 seo_props.manage_changeProperties(additional_keywords=additionalKeywords) 262 269 seo_props.manage_changeProperties(default_custom_metatags=default_custom_metatags) 270 seo_props.manage_changeProperties(metatags_order=metatags_order) 263 271 264 272 for ptype in self.portal_types.objectValues(): -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/configure.zcml
r726 r1313 4 4 xmlns:browser="http://namespaces.zope.org/browser" 5 5 xmlns:genericsetup="http://namespaces.zope.org/genericsetup" 6 xmlns:cmf="http://namespaces.zope.org/cmf" 7 > 6 xmlns:cmf="http://namespaces.zope.org/cmf"> 8 7 9 8 <five:registerPackage package="." /> … … 14 13 directory="profiles/default" 15 14 description="Install quintagroup.seoptimizer" 16 provides="Products.GenericSetup.interfaces.EXTENSION" /> 15 provides="Products.GenericSetup.interfaces.EXTENSION" 16 /> 17 17 18 18 <genericsetup:registerProfile … … 21 21 directory="profiles/uninstall" 22 22 description="Uninstall quintagroup.seoptimizer" 23 provides="Products.GenericSetup.interfaces.EXTENSION" /> 23 provides="Products.GenericSetup.interfaces.EXTENSION" 24 /> 24 25 25 26 27 28 29 30 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 /> 32 33 33 34 <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 /> 38 45 39 46 <cmf:registerDirectory name="quintagroup.seoptimizer" /> -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/interfaces.py
r387 r1313 7 7 """Returns all the existing keywords for the current content type. 8 8 """ 9 10 class 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 67 67 <property name="additional_keywords" type="lines"/> 68 68 <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> 69 87 </object> 70 88 <object name="site_properties" meta_type="Plone Property Sheet"> -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/profiles/default/viewlets.xml
r1308 r1313 2 2 <object> 3 3 <order manager="plone.htmlhead" skinname="*"> 4 <!--viewlet name="quintagroup.seoptimizer.http_equiv" /-->5 4 <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" />10 5 <viewlet name="quintagroup.seoptimizer.customscript" /> 11 6 <viewlet name="plone.resourceregistries" /> -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/tests/testQSEOptimizer.py
r1269 r1313 28 28 'meta_content' : ''} 29 29 ] 30 view_metatags = ['DC.creator', 'DC.format', 'DC.date.modified', 'DC.date.created', 'DC.type', 31 'DC.distribution', 'description', 'keywords', 'robots', 'distribution'] 30 32 31 33 global_custom_metatags = {'default_custom_metatags':'metatag1|global_metatag1value\nmetatag4|global_metatag4value'} … … 215 217 def testDescription(self): 216 218 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) 217 221 self.assert_(m, 'Description not set in') 218 222 219 223 def testKeywords(self): 220 224 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) 221 227 self.assert_(m, 'Keywords not set in') 222 228 223 229 def testRobots(self): 224 230 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) 225 233 self.assert_(m, 'Robots not set in') 226 234 227 235 def testDistribution(self): 228 236 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) 229 239 self.assert_(m, 'Distribution not set in') 230 240 … … 234 244 235 245 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) 237 249 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 238 265 239 266 def testCustomMetaTags(self): 240 267 for tag in custom_metatags: 241 268 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) 242 271 if tag['meta_content']: 243 272 self.assert_(m, "Custom meta tag %s not applied." % tag['meta_name']) … … 245 274 self.assert_(not m, "Meta tag %s has no content, but is present in the page." % tag['meta_name']) 246 275 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) 247 278 self.assert_(m, "Global custom meta tag %s not applied." % 'metatag4') 248 279 … … 253 284 html = self.publish(self.abs_path, self.basic_auth).getBody() 254 285 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) 255 288 self.assert_(not m, "Global custom meta tag %s is prosent in the page." % 'metatag4') 256 289 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) 257 292 self.assert_(m, "Global custom meta tag %s is prosent in the page." % 'metatag4') 258 293 … … 311 346 self.my_doc.manage_addProperty('qSEO_keywords', ('foo',), 'lines') 312 347 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) 314 351 self.assert_(m, "No 'foo' keyword find") 315 352 … … 317 354 self.my_doc.manage_addProperty('qSEO_keywords', ('foo', 'bar'), 'lines') 318 355 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) 320 359 self.assert_(m, "No 'foo, bar' keyword find") 321 360 … … 329 368 self.sp.additional_keywords = ('foo',) 330 369 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) 332 373 self.assert_(m, "No 'foo' keyword find") 333 374 … … 336 377 self.sp.additional_keywords = ('foo', 'bar') 337 378 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) 339 382 self.assert_(m, "No 'foo, bar' keyword find") 340 383 … … 344 387 self.my_doc.manage_addProperty('qSEO_keywords', ('baz',), 'lines') 345 388 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) 347 392 self.assert_(m, "No 'foo, bar, baz' keyword find") 348 393 … … 382 427 self.my_doc.qseo_properties_edit() 383 428 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 386 436 self.assert_(not m, 'DC meta tags avaliable when exposeDCMetaTags=False') 387 437 … … 390 440 self.my_doc.qseo_properties_edit() 391 441 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 393 449 self.assert_(m, 'DC meta tags not avaliable when createManager=True') 394 450 -
quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/util.py
r429 r1313 12 12 class SortedDict(dict): 13 13 security = ClassSecurityInfo() 14 security.declarePublic('items') 14 15 security.declarePublic('items') 15 16 def items(self): 16 primary_metatags = ['description', 'keywords']17 primary_metatags = self.pmt 17 18 lst = [(name,self[name]) for name in primary_metatags \ 18 19 if name in self.keys()] + \ … … 20 21 if name not in primary_metatags] 21 22 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) 22 36 23 37 try:
Note: See TracChangeset
for help on using the changeset viewer.