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

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

Fixed bugs in the adding Property

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