Back to index

plone3  3.1.7
backlink.py
Go to the documentation of this file.
00001 from Missing import Value as MissingValue
00002 from Products.Archetypes.interfaces import IReferenceable
00003 from Products.CMFCore.utils import getToolByName
00004 from wicked.interfaces import IWickedFilter, IAmWicked, IWickedTarget
00005 from wicked.at import config
00006 from wicked.interfaces import IATBacklinkManager, IUID
00007 from wicked.normalize import titleToNormalizedId as normalize
00008 from relation import Backlink
00009 from zope.interface import alsoProvides as mark
00010 from zope.interface import implements
00011 from wicked.utils import memoizedproperty, memoize, match, packBrain, cleanUID
00012 from zope.component import adapts
00013 
00014 
00015 class ATBacklinkManager(object):
00016     #@@ needs refactoring
00017     implements(IATBacklinkManager)
00018     adapts(IWickedFilter, IReferenceable)
00019     
00020     relation = config.BACKLINK_RELATIONSHIP
00021     refKlass = Backlink
00022 
00023     packBrain = staticmethod(packBrain)
00024     
00025     def __init__(self, wfilter, context):
00026         self.wfilter = wfilter
00027         self.context = context
00028         self.cm = wfilter.cache
00029         self.resolver = wfilter.resolver
00030         self.getMatch = wfilter.getMatch
00031         ## ATism: remove ASAP
00032         self.refcat = getToolByName(self.context, 'reference_catalog')
00033         self.suid = IUID(self.context)
00034 
00035     def getLinks(self):
00036         """
00037         Returns dataobjects representing backlinks
00038         """
00039         refbrains = self.refcat._queryFor(relationship=self.relation,
00040                                  tid=self.suid, sid=None)
00041         if refbrains:
00042             uids = [brain.sourceUID for brain in refbrains]
00043             ## XXX non-orthogonal
00044             return self.resolver.queryUIDs(uids)
00045         return []
00046     
00047     def _preplinks(self, links=dict()):
00048         return links and dict([(normalize(link), link) for link in links]) \
00049                      or dict()
00050 
00051     def manageLinks(self, new_links):
00052         # this has been heavily optimized
00053         # @@ but asyncing backlinking would help
00054                 
00055         scope=self.wfilter.scope
00056         dups = set(self.removeLinks(new_links))
00057 
00058         resolver = self.resolver
00059         norm=tuple()
00060         for link in new_links:
00061             normalled=normalize(link)
00062             norm+=normalled,
00063             self.resolver.aggregate(link, normalled, scope)
00064 
00065         for link, normalled in zip(new_links, norm):
00066             match = self.getMatch(link, resolver.agg_brains, normalled=normalled)            
00067             if not match:
00068                 match = self.getMatch(link, resolver.agg_scoped_brains, normalled=normalled)
00069             if not match:
00070                 continue
00071             if match.UID != MissingValue and match.UID in dups:
00072                 continue
00073             self.manageLink(match, normalled)
00074 
00075     def manageLink(self, obj, normalled):
00076         # need IObject iface for catalog brains
00077         if hasattr(obj, 'getObject'):
00078             # brain, other sort of pseudo object
00079             obj = obj.getObject()
00080 
00081         if not IReferenceable.providedBy(obj):
00082             # backlink not possible
00083             return
00084 
00085         mark(obj, IWickedTarget)
00086         self.refcat.addReference(obj,
00087                                  self.context,
00088                                  relationship=self.relation,
00089                                  referenceClass=self.refKlass)
00090         objuid = IUID(obj)
00091         path = '/'.join(obj.getPhysicalPath())
00092         data = dict(path=path,
00093                     icon=obj.getIcon(),
00094                     uid=objuid)
00095         
00096         self.cm.set((intern(normalled), objuid), [data])  
00097 
00098     def removeLinks(self, exclude=tuple()):
00099         oldlinks = self.getLinks()
00100         if not oldlinks:
00101             return set()
00102         
00103         exclude = self._preplinks(exclude)        
00104         dups = set([brain for brain in oldlinks if \
00105                     self.match(brain, exclude.get)])
00106         
00107         [self.remove(brain) for brain in set(oldlinks) - dups]
00108         return [self.cleanUID(b) for b in dups]
00109 
00110     cleanUID = staticmethod(cleanUID)
00111 
00112     def match(self, brain, getlink):
00113         """
00114         mmmm....turtle.
00115         @@ make efficient
00116         """
00117         link = getlink(brain.getId,
00118                        getlink(normalize(brain.Title), None))
00119         if link:
00120             return True
00121                 
00122     def remove(self, brain):
00123         #XXX needs test
00124         objs = self.refcat._resolveBrains(\
00125             self.refcat._queryFor(self.suid, brain.UID, self.relation))
00126         for obj in objs:
00127             self.refcat._deleteReference(obj)
00128             self.cm.unset(obj.targetUID, use_uid=True)
00129 
00130     def unlink(self, uid):
00131         self.cm.remove(uid)