SEO: show informative URLs (with title) when global option 'useInformativeURLs' is set

This commit is contained in:
Helmut Merz 2011-12-05 10:44:34 +01:00
parent c963f05964
commit a86c8afcfa
5 changed files with 26 additions and 38 deletions

View file

@ -58,6 +58,7 @@ from cybertools.relation.interfaces import IRelationRegistry
from cybertools.stateful.interfaces import IStateful from cybertools.stateful.interfaces import IStateful
from cybertools.text import mimetypes from cybertools.text import mimetypes
from cybertools.typology.interfaces import IType, ITypeManager from cybertools.typology.interfaces import IType, ITypeManager
from loops.browser.util import normalizeForUrl
from loops.common import adapted, baseObject from loops.common import adapted, baseObject
from loops.config.base import DummyOptions from loops.config.base import DummyOptions
from loops.i18n.browser import I18NView from loops.i18n.browser import I18NView
@ -151,6 +152,11 @@ class BaseView(GenericView, I18NView):
def name(self): def name(self):
return getName(self.context) return getName(self.context)
def makeTargetUrl(self, baseUrl, targetId, title=None):
if self.globalOptions('useInformativeURLs') and title:
return '%s/.%s-%s' % (baseUrl, targetId, normalizeForUrl(title))
return '%s/.%s' % (baseUrl, targetId)
@Lazy @Lazy
def principalId(self): def principalId(self):
principal = self.request.principal principal = self.request.principal

View file

@ -292,8 +292,7 @@ class NodeView(BaseView):
def targetUrl(self): def targetUrl(self):
t = self.targetObjectView t = self.targetObjectView
if t is not None: if t is not None:
#return '%s/.target%s' % (self.url, t.uniqueId) return self.makeTargetUrl(self.url, t.uniqueId, t.title)
return '%s/.%s' % (self.url, t.uniqueId)
return '' return ''
def renderTarget(self): def renderTarget(self):
@ -465,10 +464,10 @@ class NodeView(BaseView):
@Lazy @Lazy
def virtualTargetUrl(self): def virtualTargetUrl(self):
targetId = self.targetId target = self.virtualTargetObject
if targetId is not None: if target is not None:
#return '%s/.target%s' % (self.url, targetId) tv = BaseView(target, self.request)
return '%s/.%s' % (self.url, targetId) return self.makeTargetUrl(self.url, tv.uniqueId, tv.title)
else: else:
return self.url return self.url
@ -494,12 +493,10 @@ class NodeView(BaseView):
""" Return URL of given target view given as .XXX URL. """ Return URL of given target view given as .XXX URL.
""" """
if isinstance(target, BaseView): if isinstance(target, BaseView):
#return '%s/.target%s' % (self.url, target.uniqueId) return self.makeTargetUrl(self.url, target.uniqueId, target.title)
return '%s/.%s' % (self.url, target.uniqueId)
else: else:
#return ('%s/.target%s' % return self.makeTargetUrl(self.url, util.getUidForObject(target),
return ('%s/.%s' % target.title)
(self.url, util.getUidForObject(target)))
def getActions(self, category='object', target=None): def getActions(self, category='object', target=None):
actions = [] actions = []
@ -900,21 +897,6 @@ class NodeTraverser(ItemTraverser):
return self.context.getLoopsRoot() return self.context.getLoopsRoot()
if name.startswith('.'): if name.startswith('.'):
name = self.cleanUpTraversalStack(request, name)[1:] name = self.cleanUpTraversalStack(request, name)[1:]
#traversalStack = request._traversal_stack
#while traversalStack and traversalStack[0].startswith('.target'):
# # skip obsolete target references in the url
# name = traversalStack.pop(0)
#traversedNames = request._traversed_names
#if traversedNames:
# lastTraversed = traversedNames[-1]
# if lastTraversed.startswith('.target') and lastTraversed != name:
# # let <base .../> tag show the current object
# traversedNames[-1] = name
#if len(name) > len('.target'):
# uid = int(name[len('.target'):])
# target = util.getObjectForUid(uid)
#else:
# target = self.context.target
target = self.getTarget(name) target = self.getTarget(name)
if target is not None: if target is not None:
# remember self.context in request # remember self.context in request

View file

@ -141,7 +141,7 @@
tal:condition="nocall:target"> tal:condition="nocall:target">
<div tal:repeat="related item/resources"> <div tal:repeat="related item/resources">
<a href="#" <a href="#"
tal:attributes="href string:${view/url}/.target${related/uniqueId}; tal:attributes="href python:view.getUrlForTarget(related);
title related/description" title related/description"
tal:content="related/title">Resource Title</a> tal:content="related/title">Resource Title</a>
</div> </div>
@ -164,7 +164,7 @@
tal:condition="nocall:target"> tal:condition="nocall:target">
<div tal:repeat="related item/children"> <div tal:repeat="related item/children">
<a href="#" <a href="#"
tal:attributes="href string:${view/url}/.${related/uniqueId}; tal:attributes="href python:view.getUrlForTarget(related);
title related/description" title related/description"
tal:content="related/title">Concept Title</a> tal:content="related/title">Concept Title</a>
</div> </div>

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de # Copyright (c) 2011 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -18,10 +18,9 @@
""" """
Utilities. Utilities.
$Id$
""" """
import re
from zope.app import zapi from zope.app import zapi
from zope.app.pagetemplate import ViewPageTemplateFile from zope.app.pagetemplate import ViewPageTemplateFile
from zope.app.publisher.browser.menu import BrowserMenu from zope.app.publisher.browser.menu import BrowserMenu
@ -65,3 +64,9 @@ def html_quote(text, character_entities=((u'&', u'&amp;'), (u'<', u'&lt;' ),
for re, name in character_entities: for re, name in character_entities:
text = text.replace(re, name) text = text.replace(re, name)
return text return text
pattern = re.compile(r'[ /\?\+%]')
def normalizeForUrl(text):
return pattern.sub('-', text)

View file

@ -22,8 +22,6 @@ Base classes for layout-based views.
$Id$ $Id$
""" """
import re
from zope.app.security.interfaces import IUnauthenticatedPrincipal from zope.app.security.interfaces import IUnauthenticatedPrincipal
from zope import component from zope import component
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
@ -34,6 +32,7 @@ from zope.traversing.browser import absoluteURL
from cybertools.util import format from cybertools.util import format
from loops.common import adapted from loops.common import adapted
from loops.i18n.browser import LanguageInfo from loops.i18n.browser import LanguageInfo
from loops.browser.util import normalizeForUrl as normalize
from loops import util from loops import util
@ -167,11 +166,7 @@ class BaseView(object):
def getKeywords(self): def getKeywords(self):
return self.context.title.split() return self.context.title.split()
def getMetaDescription(self): def getMetaDescription(self):
return self.context.title return self.context.title
pattern = re.compile(r'[ /\?\+%]')
def normalize(text):
return pattern.sub('-', text)