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

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

#180: Update seoptimizer to use default ICanonicalLink adapter

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