source: products/quintagroup.seoptimizer/branches/refactoring2.3.0/quintagroup/seoptimizer/browser/views.py @ 1819

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

#142: minor cleanup of seo_context view

  • Property svn:eol-style set to native
File size: 15.8 KB
RevLine 
[1468]1from sets import Set
[1475]2from DateTime import DateTime
[401]3from Acquisition import aq_inner
[896]4from zope.component import queryAdapter
[1815]5from plone.memoize import view
[392]6from plone.app.controlpanel.form import ControlPanelView
7
[408]8from Products.Five.browser import BrowserView
[401]9from Products.CMFCore.utils import getToolByName
10from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
[1480]11from Products.CMFPlone import PloneMessageFactory as pmf
[401]12
[1463]13from quintagroup.seoptimizer import SeoptimizerMessageFactory as _
[1671]14from quintagroup.seoptimizer import interfaces
[1463]15
[1183]16SEPERATOR = '|'
[1460]17SEO_PREFIX = 'seo_'
18PROP_PREFIX = 'qSEO_'
19SUFFIX = '_override'
[1461]20PROP_CUSTOM_PREFIX = 'qSEO_custom_'
21
[408]22class SEOContext( BrowserView ):
[1506]23    """ This class contains methods that allows to edit html header meta tags.
[408]24    """
[1782]25
[1815]26    def __init__(self, *args, **kwargs):
27        super(SEOContext, self).__init__(*args, **kwargs)
28        self._seotags = self._getSEOTags()
[1782]29
[1815]30    def __getitem__(self, key):
31        return self._seotags.get(key, '')
32
33    @view.memoize
34    def _getSEOTags(self):
35        seotags = {
36            "seo_title": self.getSEOProperty( 'qSEO_title', accessor='Title' ),
37            "seo_robots": self.getSEOProperty( 'qSEO_robots', default='ALL'),
38            "seo_description": self.getSEOProperty( 'qSEO_description', accessor='Description' ),
39            "seo_distribution": self.getSEOProperty( 'qSEO_distribution', default="Global"),
40            "seo_customMetaTags": self.seo_customMetaTags(),
41            "seo_globalWithoutLocalCustomMetaTags": self.seo_globalWithoutLocalCustomMetaTags(),
42            "seo_localCustomMetaTags": self.seo_localCustomMetaTags(),
43            "seo_globalCustomMetaTags": self.seo_globalCustomMetaTags(),
44            "seo_html_comment": self.getSEOProperty( 'qSEO_html_comment', default='' ),
45            "meta_keywords": self.meta_keywords(),
46            "seo_keywords": self.seo_keywords(),
47            "seo_canonical": self.seo_canonical(),
48            # Add test properties
49            "has_seo_title": self.context.hasProperty('qSEO_title'),
50            "has_seo_robots": self.context.hasProperty('qSEO_robots'),
51            "has_seo_description": self.context.hasProperty( 'qSEO_description'),
52            "has_seo_distribution": self.context.hasProperty( 'qSEO_distribution'),
53            "has_html_comment": self.context.hasProperty('qSEO_html_comment'),
54            "has_seo_keywords": self.context.hasProperty('qSEO_keywords'),
55            "has_seo_canonical": self.context.hasProperty('qSEO_canonical'),
56            }
57        seotags["seo_nonEmptylocalMetaTags"] = bool(seotags["seo_localCustomMetaTags"])
58        return seotags
59
60       
61    def getSEOProperty( self, property_name, accessor='', default=None ):
[1506]62        """ Get value from seo property by property name.
[408]63        """
[413]64        context = aq_inner(self.context)
65
66        if context.hasProperty(property_name):
[1815]67            return context.getProperty(property_name, default)
[1475]68
[413]69        if accessor:
[1815]70            method = getattr(context, accessor, default)
[413]71            if not callable(method):
[1815]72                return default
[408]73
[413]74            # Catch AttributeErrors raised by some AT applications
75            try:
76                value = method()
77            except AttributeError:
[1815]78                value = default
[1475]79
[413]80            return value
[408]81
82
[1815]83    def isSEOTabVisibile(self):
84        context = aq_inner(self.context)
85        portal_properties = getToolByName(context, 'portal_properties')
86        seo_properties = getToolByName(portal_properties, 'seo_properties')
87        content_types_with_seoproperties = seo_properties.getProperty('content_types_with_seoproperties', '')
88        return bool(self.context.portal_type in content_types_with_seoproperties)
[408]89
[1475]90
[408]91    def seo_customMetaTags( self ):
[1819]92        """Returned seo custom metatags from default_custom_metatags property in seo_properties
[1506]93        (global seo custom metatags) with update from seo custom metatags properties in context (local seo custom metatags).
[408]94        """
[1265]95        tags = self.seo_globalCustomMetaTags()
96        loc = self.seo_localCustomMetaTags()
97        names = [i['meta_name'] for i in tags]
98        add_tags = []
99        for i in loc:
100            if i['meta_name'] in names:
101                for t in tags:
102                    if t['meta_name'] == i['meta_name']:
103                        t['meta_content'] = i['meta_content']
104            else:
105                add_tags.append(i)
106        tags.extend(add_tags)
107        return tags
108
109    def seo_globalWithoutLocalCustomMetaTags( self ):
[1819]110        """Returned seo custom metatags from default_custom_metatags property in seo_properties
[1506]111        (global seo custom metatags) without seo custom metatags from properties in context (local seo custom metatags).
[1265]112        """
113        glob = self.seo_globalCustomMetaTags()
114        loc = self.seo_localCustomMetaTags()
115        names = [i['meta_name'] for i in loc]
116        tags = []
117        for i in glob:
118            if i['meta_name'] not in names:
119                tags.append(i)
120        return tags
121
122    def seo_localCustomMetaTags( self ):
[1506]123        """ Returned seo custom metatags from properties in context (local seo custom metatags).
[1265]124        """
[408]125        result = []
126        property_prefix = 'qSEO_custom_'
127        context = aq_inner(self.context)
128        for property, value in context.propertyItems():
[1265]129            if property.startswith(property_prefix) and property[len(property_prefix):]:
[408]130                result.append({'meta_name'    : property[len(property_prefix):],
131                               'meta_content' : value})
[1265]132        return result
[408]133
[1265]134    def seo_globalCustomMetaTags( self ):
[1506]135        """ Returned seo custom metatags from default_custom_metatags property in seo_properties.
[1265]136        """
137        result = []
138        context = aq_inner(self.context)
[408]139        site_properties = getToolByName(context, 'portal_properties')
140        if hasattr(site_properties, 'seo_properties'):
[1183]141            custom_meta_tags = getattr(site_properties.seo_properties, 'default_custom_metatags', [])
142            for tag in custom_meta_tags:
143                name_value = tag.split(SEPERATOR)
[1265]144                if name_value[0]:
145                    result.append({'meta_name'    : name_value[0],
[1309]146                                   'meta_content' : len(name_value) == 2 and name_value[1] or ''})
[408]147        return result
[1265]148
[1624]149    def meta_keywords( self ):
150        """ Generate Meta Keywords from SEO properties (global and local) with Subject,
151            depending on the options in configlet.
[408]152        """
153        prop_name = 'qSEO_keywords'
154        accessor = 'Subject'
155        context = aq_inner(self.context)
[1468]156        keywords = Set([])
[408]157        pprops = getToolByName(context, 'portal_properties')
158        sheet = getattr(pprops, 'seo_properties', None)
159        method = getattr(context, accessor, None)
160        if not callable(method):
161            return None
162
163        # Catch AttributeErrors raised by some AT applications
164        try:
[1600]165            subject = Set(method())
[408]166        except AttributeError:
[1600]167            subject = keywords
[408]168
[1600]169        if sheet:
170          settings_use_keywords_sg = sheet.getProperty('settings_use_keywords_sg')
171          settings_use_keywords_lg = sheet.getProperty('settings_use_keywords_lg')
172          global_keywords = Set(sheet.getProperty('additional_keywords', None))
173          local_keywords = Set(context.getProperty(prop_name, None))
174          # Subject overrides global seo keywords and global overrides local seo keywords
175          if [settings_use_keywords_sg, settings_use_keywords_lg] == [1, 1]:
176              keywords = subject
177          # Subject overrides global seo keywords and merge global and local seo keywords
178          elif [settings_use_keywords_sg, settings_use_keywords_lg] == [1, 2]:
179              keywords = subject | local_keywords
180          # Global seo keywords overrides Subject and global overrides local seo keywords
181          elif [settings_use_keywords_sg, settings_use_keywords_lg] == [2, 1]:
182              keywords = global_keywords
183          # Global seo keywords overrides Subject and merge global and local seo keywords
184          elif [settings_use_keywords_sg, settings_use_keywords_lg] == [2, 2]:
185              keywords = global_keywords | local_keywords
186          # Merge Subject and global seo keywords and global overrides local seo keywords
187          elif [settings_use_keywords_sg, settings_use_keywords_lg] == [3, 1]:
188              keywords = subject | global_keywords
189          # Merge Subject and global seo keywords and merge global and local seo keywords
190          elif [settings_use_keywords_sg, settings_use_keywords_lg] == [3, 2]:
191              keywords = subject | global_keywords | local_keywords
192          else:
193              keywords = subject
194        else:
195            keywords = subject
[1475]196
[1638]197        return tuple(keywords)
[1600]198
[1624]199    def seo_keywords( self ):
200        """ Generate SEO Keywords from SEO properties (global merde local).
201        """
202        prop_name = 'qSEO_keywords'
203        context = aq_inner(self.context)
204        keywords = Set([])
205        pprops = getToolByName(context, 'portal_properties')
206        sheet = getattr(pprops, 'seo_properties', None)
207
208        if sheet:
209            settings_use_keywords_sg = sheet.getProperty('settings_use_keywords_sg')
210            settings_use_keywords_lg = sheet.getProperty('settings_use_keywords_lg')
211            global_keywords = Set(sheet.getProperty('additional_keywords', None))
212            local_keywords = Set(context.getProperty(prop_name, None))
213            keywords = global_keywords | local_keywords
214        else:
215            keywords = ''
[1638]216        return tuple(keywords)
[1624]217
[896]218    def seo_canonical( self ):
[1506]219        """ Generate canonical URL from SEO properties.
[896]220        """
[1671]221        purl = getToolByName(self.context, 'portal_url')()
[1675]222        canpath = queryAdapter(self.context, interfaces.ISEOCanonicalPath)
[1671]223        return purl + canpath.canonical_path()
[896]224
225
[1460]226class SEOContextPropertiesView( BrowserView ):
[1506]227    """ This class contains methods that allows to manage seo properties.
[1460]228    """
229    template = ViewPageTemplateFile('templates/seo_context_properties.pt')
230
[1461]231    def test( self, condition, first, second ):
232        """
233        """
234        return condition and first or second
[1466]235
236    def getMainDomain(self, url):
[1506]237        """ Get a main domain.
238        """
[1466]239        url = url.split('//')[-1]
240        dompath = url.split(':')[0]
241        dom = dompath.split('/')[0]
242        return '.'.join(dom.split('.')[-2:])
243
244    def validateSEOProperty(self, property, value):
[1506]245        """ Validate a seo property.
246        """
[1466]247        purl = getToolByName(self.context, 'portal_url')()
248        state = ''
249        if property == PROP_PREFIX+'canonical':
[1506]250            # validate seo canonical url property
[1466]251            pdomain = self.getMainDomain(purl)
252            if not pdomain == self.getMainDomain(value):
253                state = _('canonical_msg', default=u'Canonical URL mast be in ${pdomain} domain.', mapping={'pdomain': pdomain})
254        return state
255
[1462]256    def setProperty(self, property, value, type='string'):
[1506]257        """ Add a new property.
258
259        Sets a new property with the given id, value and type or changes it.
260        """
[1462]261        context = aq_inner(self.context)
[1466]262        state = self.validateSEOProperty(property, value)
263        if not state:
264            if context.hasProperty(property):
265                context.manage_changeProperties({property: value})
266            else:
267                context.manage_addProperty(property, value, type)
268        return state
[1461]269
270    def manageSEOProps(self, **kw):
[1506]271        """ Manage seo properties.
272        """
[1461]273        context = aq_inner(self.context)
[1466]274        state = ''
[1468]275        delete_list, seo_overrides_keys, seo_keys = [], [], []
[1460]276        seo_items = dict([(k[len(SEO_PREFIX):],v) for k,v in kw.items() if k.startswith(SEO_PREFIX)])
277        for key in seo_items.keys():
278            if key.endswith(SUFFIX):
[1468]279                seo_overrides_keys.append(key[:-len(SUFFIX)])
[1460]280            else:
[1468]281                seo_keys.append(key)
282        for seo_key in seo_keys:
283            if seo_key == 'custommetatags':
284                self.manageSEOCustomMetaTagsProperties(**kw)
285            else:
286                if seo_key in seo_overrides_keys and seo_items.get(seo_key+SUFFIX):
287                    seo_value = seo_items[seo_key]
288                    t_value = 'string'
289                    if type(seo_value)==type([]) or type(seo_value)==type(()): t_value = 'lines'
290                    state = self.setProperty(PROP_PREFIX+seo_key, seo_value, type=t_value)
291                    if state:
292                        return state
293                elif context.hasProperty(PROP_PREFIX+seo_key):
294                    delete_list.append(PROP_PREFIX+seo_key)
[1466]295        if delete_list:
296            context.manage_delProperties(delete_list)
297        return state
[1461]298
[1462]299    def setSEOCustomMetaTags(self, custommetatags):
[1506]300        """ Set seo custom metatags properties.
301        """
[1462]302        context = aq_inner(self.context)
[1463]303        for tag in custommetatags:
304            self.setProperty('%s%s' % (PROP_CUSTOM_PREFIX, tag['meta_name']), tag['meta_content'])
[1462]305
[1466]306    def delAllSEOCustomMetaTagsProperties(self):
[1506]307        """ Delete all seo custom metatags properties.
308        """
[1466]309        context = aq_inner(self.context)
[1461]310        delete_list = []
311        for property, value in context.propertyItems():
[1466]312            if property.startswith(PROP_CUSTOM_PREFIX)  and not property == PROP_CUSTOM_PREFIX:
[1461]313                delete_list.append(property)
[1466]314        if delete_list:
315            context.manage_delProperties(delete_list)
[1461]316
[1466]317    def updateSEOCustomMetaTagsProperties(self, custommetatags):
[1506]318        """ Update seo custom metatags properties.
319        """
[1461]320        context = aq_inner(self.context)
321        site_properties = getToolByName(context, 'portal_properties')
322        globalCustomMetaTags = []
323        if hasattr(site_properties, 'seo_properties'):
324            custom_meta_tags = getattr(site_properties.seo_properties, 'default_custom_metatags', [])
325            for tag in custom_meta_tags:
326                name_value = tag.split(SEPERATOR)
327                if name_value[0]:
328                    globalCustomMetaTags.append({'meta_name'    : name_value[0],
329                                                 'meta_content' : len(name_value) == 1 and '' or name_value[1]})
330        for tag in custommetatags:
331            meta_name, meta_content = tag['meta_name'], tag['meta_content']
332            if meta_name:
333                if not [gmt for gmt in globalCustomMetaTags if (gmt['meta_name']==meta_name and gmt['meta_content']==meta_content)]:
[1466]334                    self.setProperty('%s%s' % (PROP_CUSTOM_PREFIX, meta_name), meta_content)
335
336    def manageSEOCustomMetaTagsProperties(self, **kw):
[1506]337        """ Update seo custom metatags properties, if enabled checkbox override or delete properties.
338
339        Change object properties by passing either a mapping object
340        of name:value pairs {'foo':6} or passing name=value parameters.
341        """
[1461]342        context = aq_inner(self.context)
[1466]343        self.delAllSEOCustomMetaTagsProperties()
344        if kw.get('seo_custommetatags_override'):
345            custommetatags = kw.get('seo_custommetatags', {})
346            self.updateSEOCustomMetaTagsProperties(custommetatags)
[1460]347
348    def __call__( self ):
[1506]349        """ Perform the update seo properties and redirect if necessary, or render the page Call method.
[1460]350        """
351        context = aq_inner(self.context)
352        request = self.request
353        form = self.request.form
354        submitted = form.get('form.submitted', False)
355        if submitted:
[1466]356            state = self.manageSEOProps(**form)
357            if not state:
358                state = _('seoproperties_saved', default=u'Content SEO properties have been saved.')
359                context.plone_utils.addPortalMessage(state)
[1475]360                kwargs = {'modification_date' : DateTime()} 
[1675]361                context.plone_utils.contentEdit(context, **kwargs)
[1466]362                return request.response.redirect(self.context.absolute_url())
363            context.plone_utils.addPortalMessage(state, 'error')
364        return self.template()
Note: See TracBrowser for help on using the repository browser.