source: products/quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/browser/views.py @ 1466

Last change on this file since 1466 was 1466, checked in by liebster, 14 years ago

Cleaned code and added translation

  • Property svn:eol-style set to native
File size: 14.3 KB
Line 
1from Acquisition import aq_inner
2from zope.component import queryAdapter
3from plone.app.controlpanel.form import ControlPanelView
4
5from Products.Five.browser import BrowserView
6from Products.CMFCore.utils import getToolByName
7from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
8
9from quintagroup.seoptimizer import SeoptimizerMessageFactory as _
10
11SEPERATOR = '|'
12HAS_CANONICAL_PATH = True
13SEO_PREFIX = 'seo_'
14PROP_PREFIX = 'qSEO_'
15SUFFIX = '_override'
16PROP_CUSTOM_PREFIX = 'qSEO_custom_'
17
18try:
19    from quintagroup.canonicalpath.interfaces import ICanonicalPath
20except ImportError:
21    HAS_CANONICAL_PATH = False
22
23class SEOContext( BrowserView ):
24    """
25    """
26    def getSEOProperty( self, property_name, accessor='' ):
27        """
28        """
29        context = aq_inner(self.context)
30
31        if context.hasProperty(property_name):
32            return context.getProperty(property_name)
33       
34        if accessor:
35            method = getattr(context, accessor, None)
36            if not callable(method):
37                return None
38
39            # Catch AttributeErrors raised by some AT applications
40            try:
41                value = method()
42            except AttributeError:
43                value = None
44       
45            return value
46
47    def seo_title( self ):
48        """
49        """
50        return self.getSEOProperty( 'qSEO_title', accessor='Title' )
51
52    def seo_robots( self ):
53        """
54        """
55        robots = self.getSEOProperty( 'qSEO_robots' )
56        return robots and robots or 'ALL'
57
58    def seo_description( self ):
59        """
60            Generate Description from SEO properties
61        """
62       
63        return self.getSEOProperty( 'qSEO_description', accessor = 'Description')
64
65    def seo_distribution( self ):
66        """
67           Generate Description from SEO properties
68        """
69        dist = self.getSEOProperty( 'qSEO_distribution' )
70
71        return dist and dist or 'Global'
72
73    def seo_customMetaTags( self ):
74        """
75        """
76        tags = self.seo_globalCustomMetaTags()
77        loc = self.seo_localCustomMetaTags()
78
79        names = [i['meta_name'] for i in tags]
80        add_tags = []
81        for i in loc:
82            if i['meta_name'] in names:
83                for t in tags:
84                    if t['meta_name'] == i['meta_name']:
85                        t['meta_content'] = i['meta_content']
86            else:
87                add_tags.append(i)
88        tags.extend(add_tags)
89        return tags
90
91    def seo_globalWithoutLocalCustomMetaTags( self ):
92        """
93        """
94        glob = self.seo_globalCustomMetaTags()
95        loc = self.seo_localCustomMetaTags()
96        names = [i['meta_name'] for i in loc]
97        tags = []
98        for i in glob:
99            if i['meta_name'] not in names:
100                tags.append(i)
101        return tags
102
103    def seo_localCustomMetaTags( self ):
104        """
105        """
106        result = []
107        property_prefix = 'qSEO_custom_'
108        context = aq_inner(self.context)
109        for property, value in context.propertyItems():
110            if property.startswith(property_prefix) and property[len(property_prefix):]:
111                result.append({'meta_name'    : property[len(property_prefix):],
112                               'meta_content' : value})
113        return result
114
115    def seo_globalCustomMetaTags( self ):
116        """
117        """
118        result = []
119        context = aq_inner(self.context)
120        site_properties = getToolByName(context, 'portal_properties')
121        if hasattr(site_properties, 'seo_properties'):
122            custom_meta_tags = getattr(site_properties.seo_properties, 'default_custom_metatags', [])
123            for tag in custom_meta_tags:
124                name_value = tag.split(SEPERATOR)
125                if name_value[0]:
126                    result.append({'meta_name'    : name_value[0],
127                                   'meta_content' : len(name_value) == 2 and name_value[1] or ''})
128        return result
129
130    def seo_nonEmptylocalMetaTags( self ):
131        """
132        """
133        return bool(self.seo_localCustomMetaTags())
134
135    def seo_html_comment( self ):
136        """
137        """
138        html_comment = self.getSEOProperty( 'qSEO_html_comment' )
139        return html_comment and html_comment or '' 
140       
141    def seo_keywords( self ):
142        """
143           Generate Keywords from SEO properties
144        """
145
146        prop_name = 'qSEO_keywords'
147        add_keywords = 'additional_keywords'
148        accessor = 'Subject'
149        context = aq_inner(self.context)
150
151        keywords = []
152        if context.hasProperty(prop_name):
153            keywords = context.getProperty(prop_name)
154
155        pprops = getToolByName(context, 'portal_properties')
156        sheet = getattr(pprops, 'seo_properties', None)
157        if sheet and sheet.hasProperty(add_keywords):
158            keywords += sheet.getProperty(add_keywords)
159
160        if keywords:
161            return keywords
162
163        method = getattr(context, accessor, None)
164        if not callable(method):
165            return None
166
167        # Catch AttributeErrors raised by some AT applications
168        try:
169            value = method()
170        except AttributeError:
171            value = None
172
173        return value
174   
175    def seo_canonical( self ):
176        """
177           Get canonical URL
178        """
179        canonical = self.getSEOProperty( 'qSEO_canonical' )
180
181        if not canonical and HAS_CANONICAL_PATH:
182            canpath = queryAdapter(self.context, ICanonicalPath)
183            if canpath:
184                purl = getToolByName(self.context, 'portal_url')()
185                cpath = canpath.canonical_path()
186                canonical = purl + cpath
187
188        return canonical and canonical or self.context.absolute_url()
189
190
191class SEOControlPanel( ControlPanelView ):
192    """
193    """
194    template = ViewPageTemplateFile('templates/seo_controlpanel.pt')
195
196    @property
197    def portal_properties( self ):
198        """
199        """
200        context = aq_inner(self.context)
201        return getToolByName(context, 'portal_properties')
202
203    @property
204    def portal_types( self ):
205        """
206        """
207        context = aq_inner(self.context)
208        return getToolByName(context, 'portal_types')
209
210    def hasSEOAction( self, type_info ):
211        """
212        """
213        return filter(lambda x:x.id == 'seo_properties', type_info.listActions())
214
215    def test( self, condition, first, second ):
216        """
217        """
218        return condition and first or second
219
220    def getExposeDCMetaTags( self ):
221        """
222        """
223        sp = self.portal_properties.site_properties
224        return sp.getProperty('exposeDCMetaTags')
225
226    def getDefaultCustomMetatags( self ):
227        """
228        """
229        seo = self.portal_properties.seo_properties
230        return seo.getProperty('default_custom_metatags')
231
232    def getMetaTagsOrder( self ):
233        """
234        """
235        seo = self.portal_properties.seo_properties
236        return seo.getProperty('metatags_order')
237
238    def getAdditionalKeywords( self ):
239        """
240        """
241        seo = self.portal_properties.seo_properties
242        return seo.getProperty('additional_keywords')
243
244    def createMultiColumnList( self ):
245        """
246        """
247        context = aq_inner(self.context)
248        allTypes = self.portal_types.listContentTypes()
249        try:
250            return context.createMultiColumnList(allTypes, sort_on='title_or_id')
251        except AttributeError:
252            return [slist]
253
254    def __call__( self ):
255        """
256        """
257        context = aq_inner(self.context)
258        request = self.request
259
260        portalTypes=request.get( 'portalTypes', [] )
261        exposeDCMetaTags=request.get( 'exposeDCMetaTags', None )
262        additionalKeywords=request.get('additionalKeywords', [])
263        default_custom_metatags=request.get('default_custom_metatags', [])
264        metatags_order=request.get('metatags_order', [])
265
266        site_props = getToolByName(self.portal_properties, 'site_properties')
267        seo_props = getToolByName(self.portal_properties, 'seo_properties')
268
269        form = self.request.form
270        submitted = form.get('form.submitted', False)
271
272        if submitted:
273            site_props.manage_changeProperties(exposeDCMetaTags=exposeDCMetaTags)
274            seo_props.manage_changeProperties(additional_keywords=additionalKeywords)
275            seo_props.manage_changeProperties(default_custom_metatags=default_custom_metatags)
276            seo_props.manage_changeProperties(metatags_order=metatags_order)
277
278            for ptype in self.portal_types.objectValues():
279                acts = filter(lambda x: x.id == 'seo_properties', ptype.listActions())
280                action = acts and acts[0] or None
281                if ptype.getId() in portalTypes:
282                    if action is None:
283                        ptype.addAction('seo_properties',
284                                        'SEO Properties',
285                                        'string:${object_url}/@@seo-context-properties',
286                                        '',
287                                        'Modify portal content',
288                                        'object',
289                                        visible=1)
290                else:
291                    if action !=None:
292                        actions = list(ptype.listActions())
293                        ptype.deleteActions([actions.index(a) for a in actions if a.getId()=='seo_properties'])
294            return request.response.redirect('%s/%s'%(self.context.absolute_url(), '@@seo-controlpanel'))
295        else:
296            return self.template(portalTypes=portalTypes, exposeDCMetaTags=exposeDCMetaTags)
297
298    def typeInfo( self, type_name ):
299        """
300        """
301        return self.portal_types.getTypeInfo( type_name )
302
303
304class SEOContextPropertiesView( BrowserView ):
305    """
306    """
307    template = ViewPageTemplateFile('templates/seo_context_properties.pt')
308
309    def test( self, condition, first, second ):
310        """
311        """
312        return condition and first or second
313
314    def getMainDomain(self, url):
315        url = url.split('//')[-1]
316        dompath = url.split(':')[0]
317        dom = dompath.split('/')[0]
318        return '.'.join(dom.split('.')[-2:])
319
320    def validateSEOProperty(self, property, value):
321        purl = getToolByName(self.context, 'portal_url')()
322        state = ''
323        if property == PROP_PREFIX+'canonical':
324            pdomain = self.getMainDomain(purl)
325            if not pdomain == self.getMainDomain(value):
326                state = _('canonical_msg', default=u'Canonical URL mast be in ${pdomain} domain.', mapping={'pdomain': pdomain})
327        return state
328
329    def setProperty(self, property, value, type='string'):
330        context = aq_inner(self.context)
331        state = self.validateSEOProperty(property, value)
332        if not state:
333            if context.hasProperty(property):
334                context.manage_changeProperties({property: value})
335            else:
336                context.manage_addProperty(property, value, type)
337        return state
338
339    def manageSEOProps(self, **kw):
340        context = aq_inner(self.context)
341        state = ''
342        delete_list, overrides, values = [], [], []
343        seo_items = dict([(k[len(SEO_PREFIX):],v) for k,v in kw.items() if k.startswith(SEO_PREFIX)])
344        for key in seo_items.keys():
345            if key.endswith(SUFFIX):
346                overrides.append(key[:-len(SUFFIX)])
347            else:
348                values.append(key)
349        for val in values:
350            if val in overrides and seo_items.get(val+SUFFIX):
351                state = self.setProperty(PROP_PREFIX+val, seo_items[val])
352                if state:
353                    return state
354            elif context.hasProperty(PROP_PREFIX+val):
355                delete_list.append(PROP_PREFIX+val)
356        if delete_list:
357            context.manage_delProperties(delete_list)
358        self.manageSEOCustomMetaTagsProperties(**kw)
359        return state
360
361    def setSEOCustomMetaTags(self, custommetatags):
362        context = aq_inner(self.context)
363        for tag in custommetatags:
364            self.setProperty('%s%s' % (PROP_CUSTOM_PREFIX, tag['meta_name']), tag['meta_content'])
365
366    def delAllSEOCustomMetaTagsProperties(self):
367        context = aq_inner(self.context)
368        delete_list = []
369        for property, value in context.propertyItems():
370            if property.startswith(PROP_CUSTOM_PREFIX)  and not property == PROP_CUSTOM_PREFIX:
371                delete_list.append(property)
372        if delete_list:
373            context.manage_delProperties(delete_list)
374
375    def updateSEOCustomMetaTagsProperties(self, custommetatags):
376        context = aq_inner(self.context)
377        site_properties = getToolByName(context, 'portal_properties')
378        globalCustomMetaTags = []
379        if hasattr(site_properties, 'seo_properties'):
380            custom_meta_tags = getattr(site_properties.seo_properties, 'default_custom_metatags', [])
381            for tag in custom_meta_tags:
382                name_value = tag.split(SEPERATOR)
383                if name_value[0]:
384                    globalCustomMetaTags.append({'meta_name'    : name_value[0],
385                                                 'meta_content' : len(name_value) == 1 and '' or name_value[1]})
386        for tag in custommetatags:
387            meta_name, meta_content = tag['meta_name'], tag['meta_content']
388            if meta_name:
389                if not [gmt for gmt in globalCustomMetaTags if (gmt['meta_name']==meta_name and gmt['meta_content']==meta_content)]:
390                    self.setProperty('%s%s' % (PROP_CUSTOM_PREFIX, meta_name), meta_content)
391
392    def manageSEOCustomMetaTagsProperties(self, **kw):
393        context = aq_inner(self.context)
394        self.delAllSEOCustomMetaTagsProperties()
395        if kw.get('seo_custommetatags_override'):
396            custommetatags = kw.get('seo_custommetatags', {})
397            self.updateSEOCustomMetaTagsProperties(custommetatags)
398
399    def __call__( self ):
400        """
401        """
402        context = aq_inner(self.context)
403        request = self.request
404        form = self.request.form
405        submitted = form.get('form.submitted', False)
406        if submitted:
407            state = self.manageSEOProps(**form)
408            if not state:
409                state = _('seoproperties_saved', default=u'Content SEO properties have been saved.')
410                context.plone_utils.addPortalMessage(state)
411                return request.response.redirect(self.context.absolute_url())
412            context.plone_utils.addPortalMessage(state, 'error')
413        return self.template()
Note: See TracBrowser for help on using the repository browser.