source: products/quintagroup.seoptimizer/branches/refactoring2.3.0/quintagroup/seoptimizer/browser/viewlets.py @ 1815

Last change on this file since 1815 was 1779, checked in by mylan, 14 years ago

#137: Move SEO metatags to new quintagroup.seoptimizer.seotags viewlet, registered for plone.app.layout.viewlets.interfaces.IHtmlHead manager

  • Property svn:eol-style set to native
File size: 7.5 KB
Line 
1from cgi import escape
2from DateTime import DateTime
3from Acquisition import aq_inner
4
5from zope.component import queryMultiAdapter
6from zope.component import getMultiAdapter
7from plone.app.layout.viewlets.common import ViewletBase
8
9from Products.CMFPlone.utils import safe_unicode
10from Products.CMFCore.utils import getToolByName
11
12from quintagroup.seoptimizer.util import SortedDict
13from quintagroup.seoptimizer.interfaces import IMetaKeywords
14from quintagroup.seoptimizer.interfaces import IMappingMetaTags
15
16from Products.CMFPlone.PloneTool import *
17
18class SEOTagsViewlet( ViewletBase ):
19    """ Simple viewlet for custom title rendering.
20    """
21
22    def render(self):
23        TEMPLATE = '<meta name="%s" content="%s"/>'
24        return '\n'.join([TEMPLATE % (k,v) \
25                          for k,v in self.listMetaTags().items()])
26   
27    def listMetaTags(self):
28        """Calculate list metatags"""
29
30        result = SortedDict()
31
32        site_props = getToolByName(self, 'portal_properties').site_properties
33        use_all = site_props.getProperty('exposeDCMetaTags', None)
34
35        seo_context = queryMultiAdapter((self.context, self.request), name='seo_context')
36        adapter = IMappingMetaTags(self.context, None)
37        mapping_metadata = adapter and adapter.getMappingMetaTags() or SortedDict()
38
39        if not use_all:
40            metadata_names = mapping_metadata.has_key('DC.description') \
41                             and {'DC.description': mapping_metadata['DC.description']} \
42                             or SortedDict()
43            if mapping_metadata.has_key('description'):
44                metadata_names['description'] = mapping_metadata['description']
45        else:
46            metadata_names = mapping_metadata
47
48        for key, accessor in metadata_names.items():
49            if accessor == 'meta_keywords':
50                # Render all the existing keywords for the current content type
51                adapter = IMetaKeywords(self.context, None)
52                if adapter is not None:
53                    keywords = adapter.getMetaKeywords()
54                    if keywords:
55                        result['keywords'] = keywords
56                continue
57
58            method = getattr(seo_context, accessor, None)
59            if method is None:
60                method = getattr(aq_inner(self.context).aq_explicit, accessor, None)
61
62            if not callable(method):
63                continue
64
65            # Catch AttributeErrors raised by some AT applications
66            try:
67                value = method()
68            except AttributeError:
69                value = None
70
71            if not value:
72                # No data
73                continue
74            if accessor == 'Publisher' and value == 'No publisher':
75                # No publisher is hardcoded (TODO: still?)
76                continue
77            if isinstance(value, (list, tuple)):
78                # convert a list to a string
79                value = ', '.join(value)
80
81            # Special cases
82            if accessor == 'Description' and not metadata_names.has_key('description'):
83                result['description'] = value
84            elif accessor == 'Subject' and not metadata_names.has_key('keywords'):
85                result['keywords'] = value
86
87            if accessor not in ('Description', 'Subject'):
88                result[key] = value
89
90        if use_all:
91            created = self.context.CreationDate()
92
93            try:
94                effective = self.context.EffectiveDate()
95                if effective == 'None':
96                    effective = None
97                if effective:
98                    effective = DateTime(effective)
99            except AttributeError:
100                effective = None
101
102            try:
103                expires = self.context.ExpirationDate()
104                if expires == 'None':
105                    expires = None
106                if expires:
107                    expires = DateTime(expires)
108            except AttributeError:
109                expires = None
110
111            # Filter out DWIMish artifacts on effective / expiration dates
112            if effective is not None and \
113               effective > FLOOR_DATE and \
114               effective != created:
115                eff_str = effective.Date()
116            else:
117                eff_str = ''
118
119            if expires is not None and expires < CEILING_DATE:
120                exp_str = expires.Date()
121            else:
122                exp_str = ''
123
124            if exp_str or exp_str:
125                result['DC.date.valid_range'] = '%s - %s' % (eff_str, exp_str)
126
127        # add custom meta tags (added from qseo tab by user)
128        # for given context and default from configlet
129        custom_meta_tags = seo_context and seo_context.seo_customMetaTags() or []
130        for tag in custom_meta_tags:
131            if tag['meta_content']:
132                result[tag['meta_name']] = tag['meta_content']
133
134        return result
135
136
137
138class TitleCommentViewlet(ViewletBase):
139    """ Simple viewlet for custom title rendering.
140    """
141
142    def update(self):
143        self.portal_state = getMultiAdapter((self.context, self.request),
144                                            name=u'plone_portal_state')
145        self.context_state = getMultiAdapter((self.context, self.request),
146                                             name=u'plone_context_state')
147        self.page_title = self.context_state.object_title
148        self.portal_title = self.portal_state.portal_title
149
150        self.override_title = self.context.hasProperty('qSEO_title')
151        self.override_comments = self.context.hasProperty('qSEO_html_comment')
152
153    def std_title(self):
154        portal_title = safe_unicode(self.portal_title())
155        page_title = safe_unicode(self.page_title())
156        if page_title == portal_title:
157            return u"<title>%s</title>" % (escape(portal_title))
158        else:
159            return u"<title>%s &mdash; %s</title>" % (
160                escape(safe_unicode(page_title)),
161                escape(safe_unicode(portal_title)))
162
163    def render(self):
164        std_title = self.std_title()
165        seo_context = getMultiAdapter((self.context, self.request), name='seo_context')
166        if not self.override_title:
167            if not self.override_comments:
168                return std_title
169            else:
170                qseo_comments = u"<!--%s-->"%safe_unicode(seo_context.seo_html_comment())
171                return u"%s\n%s"%(std_title, qseo_comments)
172        else:
173            qseo_title = u"<title>%s</title>" % safe_unicode(seo_context.seo_title())
174            if not self.override_comments:
175                return qseo_title
176            else:
177                qseo_comments = u"<!--%s-->"%safe_unicode(seo_context.seo_html_comment())
178                return u"%s\n%s"%(qseo_title, qseo_comments)
179
180
181class CustomScriptViewlet( ViewletBase ):
182    """ Simple viewlet for custom script rendering.
183    """
184    def getCustomScript( self ):
185        context = self.context.aq_inner
186        portal_props = getToolByName(context, 'portal_properties')
187        seo_props = getToolByName(portal_props, 'seo_properties', None)
188        if seo_props is None:
189            return '' 
190        return seo_props.getProperty('custom_script', '')
191
192    def render( self ):
193        return safe_unicode("""%s"""% self.getCustomScript())
194
195
196class CanonicalUrlViewlet( ViewletBase ):
197    """ Simple viewlet for canonical url link rendering.
198    """
199
200    def render( self ):
201        seo_context = getMultiAdapter((self.context, self.request), name='seo_context')
202        return """<link rel="canonical" href="%s" />""" % seo_context.seo_canonical()
Note: See TracBrowser for help on using the repository browser.