source: products/quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/viewlets.py

Last change on this file was 3547, checked in by ktarasz, 12 years ago

fix pep8

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