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

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

#164: Add decoding to renderer of seotags viewlet, use safe_unicode

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