def catalog_object(self, object, uid=None, idxs=None, update_metadata=1): if idxs is None: idxs = [] vars = {} w = XWFIndexableObjectWrapper(vars, object) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata)
def catalog_object(self, obj, uid=None, **kwargs): if not isinstance(obj, self._get_forbidden_classes()): ob = IIndexableWrapper(obj) if kwargs.get('idxs'): # the first time we catalog an object we must catalog the # entire object uid = uid or "/".join(obj.getPhysicalPath()) if not uid in self._catalog.uids: del kwargs['idxs'] ZCatalog.catalog_object(self, ob, uid, **kwargs)
def catalog_object(self, obj, uid, idxs=None, update_metadata=1): # Wraps the object with workflow and accessibility # information just before cataloging. wftool = getToolByName(self, 'portal_workflow', None) if wftool is not None: vars = wftool.getCatalogVariablesFor(obj) else: vars = {} w = IndexableObjectWrapper(vars, obj) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata)
def catalog_object(self, object, uid, idxs=[]): # Wraps the object with workflow and accessibility # information just before cataloging. wf = getattr(self, 'portal_workflow', None) if wf is not None: vars = wf.getCatalogVariablesFor(object) else: vars = {} w = IndexableObjectWrapper(vars, object) ZCatalog.catalog_object(self, w, uid, idxs)
def catalog_object(self, object, uid, idxs=[]): # Wraps the object with workflow and accessibility # information just before cataloging. wf = getattr(self, 'portal_workflow', None) if wf is not None: vars = wf.getCatalogVariablesFor(object) else: vars = {} w = IndexableObjectWrapper(vars, object) ZCatalog.catalog_object(self, w, uid, idxs)
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1, pghandler=None): # Wraps the object with workflow and accessibility # information just before cataloging. wftool = queryUtility(IConfigurableWorkflowTool) if wftool is not None: vars = wftool.getCatalogVariablesFor(obj) else: vars = {} w = IndexableObjectWrapper(vars, obj) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler)
def catalog_object(self, object, uid, idxs=[], update_metadata=1, pghandler=None): w = object if not IIndexableObject.providedBy(object): # This is the CMF 2.2 compatible approach, which should be used going forward wrapper = component.queryMultiAdapter((object, self), IIndexableObject) if wrapper is not None: w = wrapper ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler=pghandler)
def _make_catalog(self): zcat = ZCatalog('catalog') zcat._catalog.addIndex('big', BooleanIndex('big')) zcat._catalog.addIndex('date', DateRangeIndex('date', 'start', 'end')) zcat._catalog.addIndex('num', FieldIndex('num')) zcat._catalog.addIndex('numbers', KeywordIndex('numbers')) zcat._catalog.addIndex('path', PathIndex('getPhysicalPath')) zcat._catalog.addIndex('uuid', UUIDIndex('num')) for i in range(9): obj = Dummy(i) zcat.catalog_object(obj, str(i)) return zcat
def _make_catalog(self): zcat = ZCatalog('catalog') zcat._catalog.addIndex('big', BooleanIndex('big')) zcat._catalog.addIndex('date', DateRangeIndex('date', 'start', 'end')) zcat._catalog.addIndex('num', FieldIndex('num')) zcat._catalog.addIndex('numbers', KeywordIndex('numbers')) zcat._catalog.addIndex('path', PathIndex('getPhysicalPath')) zcat._catalog.addIndex('uuid', UUIDIndex('num')) for i in range(9): obj = Dummy(i) zcat.catalog_object(obj, str(i)) return zcat
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1, pghandler=None): # Wraps the object with workflow and accessibility # information just before cataloging. if IIndexableObject.providedBy(obj): w = obj else: w = queryMultiAdapter((obj, self), IIndexableObject) if w is None: # BBB w = IndexableObjectWrapper(obj, self) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler)
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1, pghandler=None): # Wraps the object with workflow and accessibility # information just before cataloging. if IIndexableObject.providedBy(obj): w = obj else: w = queryMultiAdapter( (obj, self), IIndexableObject ) if w is None: # BBB w = IndexableObjectWrapper(obj, self) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler)
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1, pghandler=None): # Wraps the object with workflow and accessibility # information just before cataloging. # XXX: this method violates the rules for tools/utilities: # it depends on a non-utility tool wftool = getToolByName(self, 'portal_workflow', None) if wftool is not None: vars = wftool.getCatalogVariablesFor(obj) else: vars = {} w = IndexableObjectWrapper(vars, obj) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler)
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1, pghandler=None): # Wraps the object with workflow and accessibility # information just before cataloging. # XXX: this method violates the rules for tools/utilities: # it depends on a non-utility tool if IIndexableObject.providedBy(obj): w = obj else: w = queryMultiAdapter( (obj, self), IIndexableObject ) if w is None: # BBB w = IndexableObjectWrapper(obj, self) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler)
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1, pghandler=None): # Wraps the object with workflow and accessibility # information just before cataloging. # XXX: this method violates the rules for tools/utilities: # it depends on a non-utility tool if IIndexableObject.providedBy(obj): w = obj else: w = queryMultiAdapter( (obj, self), IIndexableObject ) if w is None: # BBB w = IndexableObjectWrapper(obj, self) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler)
def plone_catalog_object(self, object, uid=None, idxs=None, update_metadata=1, pghandler=None, quick=False): if idxs is None: idxs = [] self._increment_counter() w = object if not IIndexableObject.providedBy(object): # This is the CMF 2.2 compatible approach, which should be used # going forward wrapper = queryMultiAdapter((object, self), IIndexableObject) if wrapper is not None: w = wrapper ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler=pghandler, quick=quick)
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1, pghandler=None): # Wraps the object with workflow and accessibility # information just before cataloging. wftool = getToolByName(self, 'portal_workflow', None) if wftool is not None: vars = wftool.getCatalogVariablesFor(obj) else: vars = {} w = IndexableObjectWrapper(vars, obj) try: ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler) except TypeError: # BBB: for Zope 2.7 ZCatalog.catalog_object(self, w, uid, idxs, update_metadata)
def catalog_object(self, object, uid=None, idxs=None, update_metadata=1, pghandler=None): if idxs is None: idxs = [] self._increment_counter() w = object if not IIndexableObject.providedBy(object): # This is the CMF 2.2 compatible approach, which should be used # going forward wrapper = queryMultiAdapter((object, self), IIndexableObject) if wrapper is not None: w = wrapper ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler=pghandler)
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1, pghandler=None): # Wraps the object with workflow and accessibility # information just before cataloging. wftool = getToolByName(self, 'portal_workflow', None) if wftool is not None: vars = wftool.getCatalogVariablesFor(obj) else: vars = {} w = IndexableObjectWrapper(vars, obj) try: ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler) except TypeError: # BBB: for Zope 2.7 ZCatalog.catalog_object(self, w, uid, idxs, update_metadata)
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1, pghandler=None): # Wraps the object with workflow and accessibility # information just before cataloging. # XXX: this method violates the rules for tools/utilities: # it depends on a non-utility tool wftool = getToolByName(self, 'portal_workflow', None) if wftool is not None: vars = wftool.getCatalogVariablesFor(obj) else: vars = {} w = IndexableObjectWrapper(vars, obj) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler)
def _make_catalog(self): from Products.PluginIndexes.BooleanIndex.BooleanIndex import BooleanIndex from Products.PluginIndexes.DateRangeIndex.DateRangeIndex import DateRangeIndex from Products.PluginIndexes.FieldIndex.FieldIndex import FieldIndex from Products.PluginIndexes.KeywordIndex.KeywordIndex import KeywordIndex from Products.PluginIndexes.PathIndex.PathIndex import PathIndex from Products.PluginIndexes.UUIDIndex.UUIDIndex import UUIDIndex from Products.ZCatalog.ZCatalog import ZCatalog zcat = ZCatalog("catalog") zcat._catalog.addIndex("big", BooleanIndex("big")) zcat._catalog.addIndex("date", DateRangeIndex("date", "start", "end")) zcat._catalog.addIndex("num", FieldIndex("num")) zcat._catalog.addIndex("numbers", KeywordIndex("numbers")) zcat._catalog.addIndex("path", PathIndex("getPhysicalPath")) zcat._catalog.addIndex("uuid", UUIDIndex("num")) for i in range(9): obj = dummy(i) zcat.catalog_object(obj, str(i)) return zcat
def catalog_object(self, object, uid, idxs=[], update_metadata=1, pghandler=None): self._increment_counter() # Wraps the object with workflow and accessibility # information just before cataloging. wf = getattr(self, 'portal_workflow', None) # A comment for all the frustrated developers which aren't able to pin # point the code which adds the review_state to the catalog. :) # The review_state var and some other workflow vars are added to the # indexable object wrapper throught the code in the following lines if wf is not None: vars = wf.getCatalogVariablesFor(object) else: vars = {} portal = aq_parent(aq_inner(self)) w = getMultiAdapter((object, portal), IIndexableObjectWrapper) w.update(vars) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler=pghandler)
def _make_catalog(self): from Products.PluginIndexes.BooleanIndex.BooleanIndex import \ BooleanIndex from Products.PluginIndexes.DateRangeIndex.DateRangeIndex import \ DateRangeIndex from Products.PluginIndexes.FieldIndex.FieldIndex import FieldIndex from Products.PluginIndexes.KeywordIndex.KeywordIndex import \ KeywordIndex from Products.PluginIndexes.PathIndex.PathIndex import PathIndex from Products.PluginIndexes.UUIDIndex.UUIDIndex import UUIDIndex from Products.ZCatalog.ZCatalog import ZCatalog zcat = ZCatalog('catalog') zcat._catalog.addIndex('big', BooleanIndex('big')) zcat._catalog.addIndex('date', DateRangeIndex('date', 'start', 'end')) zcat._catalog.addIndex('num', FieldIndex('num')) zcat._catalog.addIndex('numbers', KeywordIndex('numbers')) zcat._catalog.addIndex('path', PathIndex('getPhysicalPath')) zcat._catalog.addIndex('uuid', UUIDIndex('num')) for i in range(9): obj = dummy(i) zcat.catalog_object(obj, str(i)) return zcat
def catalog_object(self, obj, uid=None, **kwargs): """Use the relative path from the portal root as uid Ordinary the catalog is using the path from root towards object but we want only a relative path from the portal root Note: This method could be optimized by improving the calculation of the relative path like storing the portal root physical path in a _v_ var. """ portal_path_len = getattr(aq_base(self), '_v_portal_path_len', None) if not portal_path_len: # cache the lenght of the portal path in a _v_ var urlTool = getToolByName(self, 'portal_url') portal_path = urlTool.getPortalObject().getPhysicalPath() portal_path_len = len(portal_path) self._v_portal_path_len = portal_path_len relpath = obj.getPhysicalPath()[portal_path_len:] uid = '/'.join(relpath) __traceback_info__ = (repr(obj), uid) ZCatalog.catalog_object(self, obj, uid, **kwargs)
def catalog_object(self, obj, uid=None, **kwargs): """Use the relative path from the portal root as uid Ordinary the catalog is using the path from root towards object but we want only a relative path from the portal root Note: This method could be optimized by improving the calculation of the relative path like storing the portal root physical path in a _v_ var. """ portal_path_len = getattr(aq_base(self), '_v_portal_path_len', None) if not portal_path_len: # cache the lenght of the portal path in a _v_ var urlTool = getToolByName(self, 'portal_url') portal_path = urlTool.getPortalObject().getPhysicalPath() portal_path_len = len(portal_path) self._v_portal_path_len = portal_path_len relpath = obj.getPhysicalPath()[portal_path_len:] uid = '/'.join(relpath) __traceback_info__ = (repr(obj), uid) ZCatalog.catalog_object(self, obj, uid, **kwargs)
def catalog_object(self, object, uid, idxs=[], update_metadata=1, pghandler=None): w = IndexableObjectWrapper(object) try: # pghandler argument got added in Zope 2.8 ZCatalog.catalog_object(self, w, uid, idxs, update_metadata, pghandler=pghandler) except TypeError: try: # update_metadata argument got added somewhere into # the Zope 2.6 line (?) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata) except TypeError: ZCatalog.catalog_object(self, w, uid, idxs)
class TestCatalogReport(cleanup.CleanUp, unittest.TestCase): def setUp(self): cleanup.CleanUp.setUp(self) from Products.ZCatalog.ZCatalog import ZCatalog self.zcat = ZCatalog('catalog') self.zcat.long_query_time = 0.0 self._add_indexes() for i in range(9): obj = dummy(i) self.zcat.catalog_object(obj, str(i)) def _add_indexes(self): from Products.PluginIndexes.FieldIndex.FieldIndex import FieldIndex from Products.PluginIndexes.KeywordIndex.KeywordIndex import \ KeywordIndex num = FieldIndex('num') self.zcat._catalog.addIndex('num', num) big = FieldIndex('big') self.zcat._catalog.addIndex('big', big) numbers = KeywordIndex('numbers') self.zcat._catalog.addIndex('numbers', numbers) def test_ReportLength(self): """ tests the report aggregation """ self.zcat.manage_resetCatalogReport() self.zcat.searchResults(numbers=4, sort_on='num') self.zcat.searchResults(numbers=1, sort_on='num') self.zcat.searchResults(numbers=3, sort_on='num') self.zcat.searchResults(big=True, sort_on='num') self.zcat.searchResults(big=True, sort_on='num') self.zcat.searchResults(big=False, sort_on='num') self.zcat.searchResults(num=[5, 4, 3], sort_on='num') self.zcat.searchResults(num=(3, 4, 5), sort_on='num') self.assertEqual(4, len(self.zcat.getCatalogReport())) def test_ReportCounter(self): """ tests the counter of equal queries """ self.zcat.manage_resetCatalogReport() self.zcat.searchResults(numbers=5, sort_on='num') self.zcat.searchResults(numbers=6, sort_on='num') self.zcat.searchResults(numbers=8, sort_on='num') r = self.zcat.getCatalogReport()[0] self.assertEqual(r['counter'], 3) def test_ReportKey(self): """ tests the query keys for uniqueness """ # query key 1 key = ('sort_on', ('big', 'True')) self.zcat.manage_resetCatalogReport() self.zcat.searchResults(big=True, sort_on='num') self.zcat.searchResults(big=True, sort_on='num') r = self.zcat.getCatalogReport()[0] self.assertEqual(r['query'], key) self.assertEqual(r['counter'], 2) # query key 2 key = ('sort_on', ('big', 'False')) self.zcat.manage_resetCatalogReport() self.zcat.searchResults(big=False, sort_on='num') r = self.zcat.getCatalogReport()[0] self.assertEqual(r['query'], key) self.assertEqual(r['counter'], 1) # query key 3 key = ('sort_on', ('num', '[3, 4, 5]')) self.zcat.manage_resetCatalogReport() self.zcat.searchResults(num=[5, 4, 3], sort_on='num') self.zcat.searchResults(num=(3, 4, 5), sort_on='num') r = self.zcat.getCatalogReport()[0] self.assertEqual(r['query'], key) self.assertEqual(r['counter'], 2)
class UnicodeTextIndexCatalogTest(unittest.TestCase): def setUp(self): self.cat = ZCatalog("catalog") self.cat.addIndex('text',"TextIndex") self.cat.addColumn('text') self.cat.addIndex('kw','KeywordIndex') self.cat.addColumn('kw') t1 = TO('the quick brown fox jumps over the lazy dog',['quick','fox']) t2 = TO('i am the nice alien from the future',['alien','future']) t3 = TO('i am a brown fox dancing with a future alien',['zerstört','könnten']) t4 = TO('i am a brown ' + unicode('fox') + ' dancing with a future alien',[]) t5 = TO(""" Die USA und Großbritannien können nach der Zerstörung der afghanischen Luftabwehr nun rund um die Uhr Angriffe fliegen. Das gab Verteidigungsminister Donald Rumsfeld bekannt. Bei den dreitägigen Angriffen seien auch bis auf einen alle Flugplätze der Taliban zerstört worden. Rumsfeld erklärte weiter, er könne die Berichte nicht bestätigen, wonach bei den amerikanischen Angriffen vier afghanische Mitarbeiter einer von den UN finanzierten Hilfsorganisation getötet wurden. Diese könnten auch durch Gegenfeuer der Taliban getötet worden sein. """,[unicode('dreitägigen','latin1'),'zerstört']) self.cat.catalog_object(t1,"o1") self.cat.catalog_object(t2,"o2") self.cat.catalog_object(t3,"o3") self.cat.catalog_object(t4,"o4") self.cat.catalog_object(t5,"o5") self.tests = [('quick',('o1',)), ('fox',('o1','o3','o4')), ('afghanischen', ('o5',)), ('dreitägigen',('o5',)) ] self.kw_tests = [ ('quick',('o1',) ), ('zerstört',('o3','o5')), ('dreitägigen',('o5',)) ] def _doTests(self,tests,field,test_unicode=0): for q,objs in tests: if test_unicode: res=self.cat.searchResults({field:{'query':unicode(q,'latin1')}}) else: res=self.cat.searchResults({field:{'query':q}}) got = [ x.getURL() for x in res] got.sort() expected = list(objs) expected.sort() assert got == expected, \ "%s: got: %s, expected: %s" % (q,got,expected) def testAsciiQuery(self): """ ascii query textindex """ self._doTests(self.tests, 'text', test_unicode=0) def testUnicodeQuery(self): """ unicode query textindex """ self._doTests(self.tests, 'text', test_unicode=1)
class TestZCatalog(unittest.TestCase): def setUp(self): from Products.ZCatalog.ZCatalog import ZCatalog self._catalog = ZCatalog('Catalog') self._catalog.resolve_path = self._resolve_num self._catalog.addIndex('title', 'KeywordIndex') self._catalog.addColumn('title') self.upper = 10 self.d = {} for x in range(0, self.upper): # make uid a string of the number ob = zdummy(x) self.d[str(x)] = ob self._catalog.catalog_object(ob, str(x)) def _resolve_num(self, num): return self.d[num] def test_z2interfaces(self): from Interface.Verify import verifyClass from Products.ZCatalog.IZCatalog import IZCatalog from Products.ZCatalog.ZCatalog import ZCatalog verifyClass(IZCatalog, ZCatalog) def test_z3interfaces(self): from Products.ZCatalog.interfaces import IZCatalog from Products.ZCatalog.ZCatalog import ZCatalog from zope.interface.verify import verifyClass verifyClass(IZCatalog, ZCatalog) def testGetMetadataForUID(self): testNum = str(self.upper - 3) # as good as any.. data = self._catalog.getMetadataForUID(testNum) self.assertEqual(data['title'], testNum) def testGetIndexDataForUID(self): testNum = str(self.upper - 3) data = self._catalog.getIndexDataForUID(testNum) self.assertEqual(data['title'][0], testNum) def testSearch(self): query = {'title': ['5', '6', '7']} sr = self._catalog.searchResults(query) self.assertEqual(len(sr), 3) sr = self._catalog.search(query) self.assertEqual(len(sr), 3) def testUpdateMetadata(self): self._catalog.catalog_object(zdummy(1), '1') data = self._catalog.getMetadataForUID('1') self.assertEqual(data['title'], '1') self._catalog.catalog_object(zdummy(2), '1', update_metadata=0) data = self._catalog.getMetadataForUID('1') self.assertEqual(data['title'], '1') self._catalog.catalog_object(zdummy(2), '1', update_metadata=1) data = self._catalog.getMetadataForUID('1') self.assertEqual(data['title'], '2') # update_metadata defaults to true, test that here self._catalog.catalog_object(zdummy(1), '1') data = self._catalog.getMetadataForUID('1') self.assertEqual(data['title'], '1') def testReindexIndexDoesntDoMetadata(self): self.d['0'].num = 9999 self._catalog.reindexIndex('title', {}) data = self._catalog.getMetadataForUID('0') self.assertEqual(data['title'], '0') def testReindexIndexesFalse(self): # setup false_id = self.upper + 1 ob = zdummyFalse(false_id) self.d[str(false_id)] = ob self._catalog.catalog_object(ob, str(false_id)) # test, object evaluates to false; there was bug which caused the # object to be removed from index ob.num = 9999 self._catalog.reindexIndex('title', {}) result = self._catalog(title='9999') self.assertEquals(1, len(result)) def testBooleanEvalOn_manage_catalogObject(self): self.d['11'] = dummyLenFail(11, self.fail) self.d['12'] = dummyNonzeroFail(12, self.fail) # create a fake response that doesn't bomb on manage_catalogObject() class myresponse: def redirect(self, url): pass # this next call should not fail self._catalog.manage_catalogObject(None, myresponse(), 'URL1', urls=('11', '12')) def testBooleanEvalOn_refreshCatalog_getobject(self): # wrap catalog under the fake parent providing unrestrictedTraverse() catalog = self._catalog.__of__(fakeparent(self.d)) # replace entries to test refreshCatalog self.d['0'] = dummyLenFail(0, self.fail) self.d['1'] = dummyNonzeroFail(1, self.fail) # this next call should not fail catalog.refreshCatalog() for uid in ('0', '1'): rid = catalog.getrid(uid) # neither should these catalog.getobject(rid) def test_getobject_doesntMaskTraversalErrorsAndDoesntDelegateTo_resolve_url( self): # wrap catalog under the fake parent providing unrestrictedTraverse() catalog = self._catalog.__of__(fakeparent(self.d)) # make resolve_url fail if ZCatalog falls back on it def resolve_url(path, REQUEST): self.fail(".resolve_url() should not be called by .getobject()") catalog.resolve_url = resolve_url # traversal should work at first rid0 = catalog.getrid('0') # lets set it up so the traversal fails del self.d['0'] self.assertRaises(FakeTraversalError, catalog.getobject, rid0, REQUEST=object()) # and if there is a None at the traversal point, that's where it should return self.d['0'] = None self.assertEquals(catalog.getobject(rid0), None)
class LinkMapTool(UniqueObject, BTreeFolder2): __implements__ = (ILinkMapTool) id = 'portal_linkmap' meta_type = 'LinkMap Tool' security = AccessControl.ClassSecurityInfo() manage_options=(( {'label':'Overview', 'action':'manage_overview'}, { 'label' : 'Catalog', 'action' : 'manage_catalog'}, ) + BTreeFolder2.manage_options ) ## ZMI methods security.declareProtected(ManagePortal, 'manage_overview') manage_overview = PageTemplateFile('zpt/explainLinkMapTool', globals() ) security.declareProtected(ManagePortal, 'manage_catalog') def manage_catalog(self, REQUEST=None): """Access to the ZCatalog""" if REQUEST is not None: REQUEST['RESPONSE'].redirect(self.catalog.absolute_url()+'/manage_catalogView') def __init__(self, *args, **kw): BTreeFolder2.__init__(self, *args, **kw) self._create_catalog() self._linkrange = (1,3) # currently unused; just a marker security.declarePrivate("_create_catalog") def _create_catalog(self): """Creates the ZCatalog instance for searching links""" # self.catalog = ZCatalog('catalog').__of__(self) self.catalog = ZCatalog('catalog') self.catalog.addIndex('source', 'FieldIndex') self.catalog.addIndex('strength', 'FieldIndex') self.catalog.addColumn('target') self.catalog.addColumn('category') self.catalog.addColumn('strength') self.catalog.addColumn('title') self._p_changed=1 security.declareProtected('LinkMap: Add Link', 'addLink') def addLink(self, source, target, title, category, strength, context=None): """Create a link""" id = self.generateId() self._setObject(id, ExtendedLink(id)) ob = getattr(self, id) ob.edit(source, target, title, category, strength) self.catalog.catalog_object(ob) security.declarePublic('searchLinks') def searchLinks(self, source=None, context=None): """Return all links for a particular source and context""" # FIXME: do we have to worry about 'latest' translation? results = self.catalog(source=source, sort_on='strength', sort_order='descending') return results def deleteLinks(self,objectId,version=None): """Delete all links for which the objectId is either source or target""" # This code assumes a ZRepository instance at /content myhost = urlparse.urlparse(self.REQUEST.SERVER_URL)[1] mypath = '/'.join(filter(None,['/content',objectId,version])) mylinks = [] # FIXME: once a better storage and search interface exists, we can use that for link in self.objectValues('Extended Link'): #Check source tokens = urlparse.urlparse(link.source) if (tokens[1] or myhost) == myhost and tokens[2].startswith(mypath): mylinks.append(link.id) else: #Check target tokens = urlparse.urlparse(link.target) if (tokens[1] or myhost) == myhost and tokens[2].startswith(mypath): mylinks.append(link.id) # Blow'em away! self.manage_delObjects(mylinks) security.setPermissionDefault('LinkMap: Add Link', ('Manager', 'Owner',))
class LinkMapTool(UniqueObject, BTreeFolder2): __implements__ = ILinkMapTool id = "portal_linkmap" meta_type = "LinkMap Tool" security = AccessControl.ClassSecurityInfo() manage_options = ( {"label": "Overview", "action": "manage_overview"}, {"label": "Catalog", "action": "manage_catalog"}, ) + BTreeFolder2.manage_options ## ZMI methods security.declareProtected(ManagePortal, "manage_overview") manage_overview = PageTemplateFile("zpt/explainLinkMapTool", globals()) security.declareProtected(ManagePortal, "manage_catalog") def manage_catalog(self, REQUEST=None): """Access to the ZCatalog""" if REQUEST is not None: REQUEST["RESPONSE"].redirect(self.catalog.absolute_url() + "/manage_catalogView") def __init__(self, *args, **kw): BTreeFolder2.__init__(self, *args, **kw) self._create_catalog() self._linkrange = (1, 3) # currently unused; just a marker security.declarePrivate("_create_catalog") def _create_catalog(self): """Creates the ZCatalog instance for searching links""" # self.catalog = ZCatalog('catalog').__of__(self) self.catalog = ZCatalog("catalog") self.catalog.addIndex("source", "FieldIndex") self.catalog.addIndex("strength", "FieldIndex") self.catalog.addColumn("target") self.catalog.addColumn("category") self.catalog.addColumn("strength") self.catalog.addColumn("title") self._p_changed = 1 security.declareProtected("LinkMap: Add Link", "addLink") def addLink(self, source, target, title, category, strength, context=None): """Create a link""" id = self.generateId() self._setObject(id, ExtendedLink(id)) ob = getattr(self, id) ob.edit(source, target, title, category, strength) self.catalog.catalog_object(ob) security.declarePublic("searchLinks") def searchLinks(self, source=None, context=None): """Return all links for a particular source and context""" # FIXME: do we have to worry about 'latest' translation? results = self.catalog(source=source, sort_on="strength", sort_order="descending") return results def deleteLinks(self, objectId, version=None): """Delete all links for which the objectId is either source or target""" # This code assumes a ZRepository instance at /content myhost = urlparse.urlparse(self.REQUEST.SERVER_URL)[1] mypath = "/".join(filter(None, ["/content", objectId, version])) mylinks = [] # FIXME: once a better storage and search interface exists, we can use that for link in self.objectValues("Extended Link"): # Check source tokens = urlparse.urlparse(link.source) if (tokens[1] or myhost) == myhost and tokens[2].startswith(mypath): mylinks.append(link.id) else: # Check target tokens = urlparse.urlparse(link.target) if (tokens[1] or myhost) == myhost and tokens[2].startswith(mypath): mylinks.append(link.id) # Blow'em away! self.manage_delObjects(mylinks) security.setPermissionDefault("LinkMap: Add Link", ("Manager", "Owner"))
class TestIndexedAttrs(ZopeTestCase.ZopeTestCase): def afterSetUp(self): self.catalog = ZCatalog("catalog") self.folder._setObject("dummy", Dummy("dummy")) self.dummy = self.folder.dummy self.physical_path = "/".join(self.dummy.getPhysicalPath()) self.custom_path = "/".join(self.dummy.getCustomPath()) self.string_path = self.dummy.getStringPath() def addIndex(self, id="path", extra=None): self.catalog.addIndex(id, "ExtendedPathIndex", extra) return self.catalog.Indexes[id] def testAddIndex(self): self.catalog.addIndex("path", "ExtendedPathIndex") try: self.catalog.Indexes["path"] except KeyError: self.fail("Failed to create index") def testDefaultIndexedAttrs(self): # By default we don't have indexed_attrs at all idx = self.addIndex() self.failIf(hasattr(idx, "indexed_attrs")) def testDefaultIndexSourceNames(self): # However, getIndexSourceName returns 'getPhysicalPath' idx = self.addIndex() self.assertEqual(idx.getIndexSourceNames(), ("getPhysicalPath",)) def testDefaultIndexObject(self): # By default PathIndex indexes getPhysicalPath idx = self.addIndex() idx.index_object(123, self.dummy) self.assertEqual(idx.getEntryForObject(123), self.physical_path) def testDefaultSearchObject(self): # We can find the object in the catalog by physical path self.addIndex() self.catalog.catalog_object(self.dummy) self.assertEqual(len(self.catalog(path=self.physical_path)), 1) def testDefaultSearchDictSyntax(self): # PathIndex supports dictionary syntax for queries self.addIndex() self.catalog.catalog_object(self.dummy) self.assertEqual(len(self.catalog(path={"query": self.physical_path})), 1) def testExtraAsRecord(self): # 'extra' can be a record type object idx = self.addIndex(extra=Record(indexed_attrs="getCustomPath")) self.assertEqual(idx.indexed_attrs, ("getCustomPath",)) def testExtraAsMapping(self): # or a dictionary idx = self.addIndex(extra={"indexed_attrs": "getCustomPath"}) self.assertEqual(idx.indexed_attrs, ("getCustomPath",)) def testCustomIndexSourceNames(self): # getIndexSourceName returns the indexed_attrs idx = self.addIndex(extra={"indexed_attrs": "getCustomPath"}) self.assertEqual(idx.getIndexSourceNames(), ("getCustomPath",)) def testCustomIndexObject(self): # PathIndex indexes getCustomPath idx = self.addIndex(extra={"indexed_attrs": "getCustomPath"}) idx.index_object(123, self.dummy) self.assertEqual(idx.getEntryForObject(123), self.custom_path) def testCustomSearchObject(self): # We can find the object in the catalog by custom path self.addIndex(extra={"indexed_attrs": "getCustomPath"}) self.catalog.catalog_object(self.dummy) self.assertEqual(len(self.catalog(path=self.custom_path)), 1) def testStringIndexObject(self): # PathIndex accepts a path as tuple or string idx = self.addIndex(extra={"indexed_attrs": "getStringPath"}) idx.index_object(123, self.dummy) self.assertEqual(idx.getEntryForObject(123), self.string_path) def testStringSearchObject(self): # And we can find the object in the catalog again self.addIndex(extra={"indexed_attrs": "getStringPath"}) self.catalog.catalog_object(self.dummy) self.assertEqual(len(self.catalog(path=self.string_path)), 1) def testIdIndexObject(self): # PathIndex prefers an attribute matching its id over getPhysicalPath idx = self.addIndex(id="getId") idx.index_object(123, self.dummy) self.assertEqual(idx.getEntryForObject(123), "dummy") def testIdIndexObject(self): # Using indexed_attr overrides this behavior idx = self.addIndex(id="getId", extra={"indexed_attrs": "getCustomPath"}) idx.index_object(123, self.dummy) self.assertEqual(idx.getEntryForObject(123), self.custom_path) def testListIndexedAttr(self): # indexed_attrs can be a list idx = self.addIndex(id="getId", extra={"indexed_attrs": ["getCustomPath", "foo"]}) # only the first attribute is used self.assertEqual(idx.getIndexSourceNames(), ("getCustomPath",)) def testStringIndexedAttr(self): # indexed_attrs can also be a comma separated string idx = self.addIndex(id="getId", extra={"indexed_attrs": "getCustomPath, foo"}) # only the first attribute is used self.assertEqual(idx.getIndexSourceNames(), ("getCustomPath",)) def testEmtpyListAttr(self): # Empty indexed_attrs falls back to defaults idx = self.addIndex(extra={"indexed_attrs": []}) self.assertEqual(idx.getIndexSourceNames(), ("getPhysicalPath",)) def testEmtpyStringAttr(self): # Empty indexed_attrs falls back to defaults idx = self.addIndex(extra={"indexed_attrs": ""}) self.assertEqual(idx.getIndexSourceNames(), ("getPhysicalPath",))
class TestZCatalog(unittest.TestCase): def setUp(self): from Products.ZCatalog.ZCatalog import ZCatalog self._catalog = ZCatalog('Catalog') self._catalog.resolve_path = self._resolve_num self._catalog.addIndex('title', 'KeywordIndex') self._catalog.addColumn('title') self.upper = 10 self.d = {} for x in range(0, self.upper): # make uid a string of the number ob = zdummy(x) self.d[str(x)] = ob self._catalog.catalog_object(ob, str(x)) def _resolve_num(self, num): return self.d[num] def test_z2interfaces(self): from Interface.Verify import verifyClass from Products.ZCatalog.IZCatalog import IZCatalog from Products.ZCatalog.ZCatalog import ZCatalog verifyClass(IZCatalog, ZCatalog) def test_z3interfaces(self): from Products.ZCatalog.interfaces import IZCatalog from Products.ZCatalog.ZCatalog import ZCatalog from zope.interface.verify import verifyClass verifyClass(IZCatalog, ZCatalog) def testGetMetadataForUID(self): testNum = str(self.upper - 3) # as good as any.. data = self._catalog.getMetadataForUID(testNum) self.assertEqual(data['title'], testNum) def testGetIndexDataForUID(self): testNum = str(self.upper - 3) data = self._catalog.getIndexDataForUID(testNum) self.assertEqual(data['title'][0], testNum) def testSearch(self): query = {'title': ['5','6','7']} sr = self._catalog.searchResults(query) self.assertEqual(len(sr), 3) sr = self._catalog.search(query) self.assertEqual(len(sr), 3) def testUpdateMetadata(self): self._catalog.catalog_object(zdummy(1), '1') data = self._catalog.getMetadataForUID('1') self.assertEqual(data['title'], '1') self._catalog.catalog_object(zdummy(2), '1', update_metadata=0) data = self._catalog.getMetadataForUID('1') self.assertEqual(data['title'], '1') self._catalog.catalog_object(zdummy(2), '1', update_metadata=1) data = self._catalog.getMetadataForUID('1') self.assertEqual(data['title'], '2') # update_metadata defaults to true, test that here self._catalog.catalog_object(zdummy(1), '1') data = self._catalog.getMetadataForUID('1') self.assertEqual(data['title'], '1') def testReindexIndexDoesntDoMetadata(self): self.d['0'].num = 9999 self._catalog.reindexIndex('title', {}) data = self._catalog.getMetadataForUID('0') self.assertEqual(data['title'], '0') def testReindexIndexesFalse(self): # setup false_id = self.upper + 1 ob = zdummyFalse(false_id) self.d[str(false_id)] = ob self._catalog.catalog_object(ob, str(false_id)) # test, object evaluates to false; there was bug which caused the # object to be removed from index ob.num = 9999 self._catalog.reindexIndex('title', {}) result = self._catalog(title='9999') self.assertEquals(1, len(result)) def testBooleanEvalOn_manage_catalogObject(self): self.d['11'] = dummyLenFail(11, self.fail) self.d['12'] = dummyNonzeroFail(12, self.fail) # create a fake response that doesn't bomb on manage_catalogObject() class myresponse: def redirect(self, url): pass # this next call should not fail self._catalog.manage_catalogObject(None, myresponse(), 'URL1', urls=('11', '12')) def testBooleanEvalOn_refreshCatalog_getobject(self): # wrap catalog under the fake parent providing unrestrictedTraverse() catalog = self._catalog.__of__(fakeparent(self.d)) # replace entries to test refreshCatalog self.d['0'] = dummyLenFail(0, self.fail) self.d['1'] = dummyNonzeroFail(1, self.fail) # this next call should not fail catalog.refreshCatalog() for uid in ('0', '1'): rid = catalog.getrid(uid) # neither should these catalog.getobject(rid) def test_getobject_doesntMaskTraversalErrorsAndDoesntDelegateTo_resolve_url(self): # wrap catalog under the fake parent providing unrestrictedTraverse() catalog = self._catalog.__of__(fakeparent(self.d)) # make resolve_url fail if ZCatalog falls back on it def resolve_url(path, REQUEST): self.fail(".resolve_url() should not be called by .getobject()") catalog.resolve_url = resolve_url # traversal should work at first rid0 = catalog.getrid('0') # lets set it up so the traversal fails del self.d['0'] self.assertRaises(FakeTraversalError, catalog.getobject, rid0, REQUEST=object()) # and if there is a None at the traversal point, that's where it should return self.d['0'] = None self.assertEquals(catalog.getobject(rid0), None)
def catalog_object(self, obj, uid, *args, **kwargs): search_obj = ISearchableMessage(obj) ZCatalog.catalog_object(self, search_obj, uid, *args, **kwargs)
class TestCatalogReport(cleanup.CleanUp, unittest.TestCase): def setUp(self): cleanup.CleanUp.setUp(self) from Products.ZCatalog.ZCatalog import ZCatalog self.zcat = ZCatalog('catalog') self.zcat.long_query_time = 0.0 self._add_indexes() for i in range(9): obj = dummy(i) self.zcat.catalog_object(obj, str(i)) def _add_indexes(self): from Products.PluginIndexes.FieldIndex.FieldIndex import FieldIndex from Products.PluginIndexes.KeywordIndex.KeywordIndex import \ KeywordIndex num = FieldIndex('num') self.zcat._catalog.addIndex('num', num) big = FieldIndex('big') self.zcat._catalog.addIndex('big', big) numbers = KeywordIndex('numbers') self.zcat._catalog.addIndex('numbers', numbers) def test_ReportLength(self): """ tests the report aggregation """ self.zcat.manage_resetCatalogReport() self.zcat.searchResults(numbers=4, sort_on='num') self.zcat.searchResults(numbers=1, sort_on='num') self.zcat.searchResults(numbers=3, sort_on='num') self.zcat.searchResults(big=True, sort_on='num') self.zcat.searchResults(big=True, sort_on='num') self.zcat.searchResults(big=False, sort_on='num') self.zcat.searchResults(num=[5, 4, 3], sort_on='num') self.zcat.searchResults(num=(3, 4, 5), sort_on='num') self.assertEqual(4, len(self.zcat.getCatalogReport())) def test_ReportCounter(self): """ tests the counter of equal queries """ self.zcat.manage_resetCatalogReport() self.zcat.searchResults(numbers=5, sort_on='num') self.zcat.searchResults(numbers=6, sort_on='num') self.zcat.searchResults(numbers=8, sort_on='num') r = self.zcat.getCatalogReport()[0] self.assertEqual(r['counter'], 3) def test_ReportKey(self): """ tests the query keys for uniqueness """ # query key 1 key = ('sort_on', ('big', 'True')) self.zcat.manage_resetCatalogReport() self.zcat.searchResults(big=True, sort_on='num') self.zcat.searchResults(big=True, sort_on='num') r = self.zcat.getCatalogReport()[0] self.assertEqual(r['query'], key) self.assertEqual(r['counter'], 2) # query key 2 key = ('sort_on', ('big', 'False')) self.zcat.manage_resetCatalogReport() self.zcat.searchResults(big=False, sort_on='num') r = self.zcat.getCatalogReport()[0] self.assertEqual(r['query'], key) self.assertEqual(r['counter'], 1) # query key 3 key = ('sort_on', ('num', '[3, 4, 5]')) self.zcat.manage_resetCatalogReport() self.zcat.searchResults(num=[5, 4, 3], sort_on='num') self.zcat.searchResults(num=(3, 4, 5), sort_on='num') r = self.zcat.getCatalogReport()[0] self.assertEqual(r['query'], key) self.assertEqual(r['counter'], 2)
def catalog_object(self, obj, uid, idxs=None, update_metadata=1): # Wraps the object with workflow and accessibility # information just before cataloging. wftool = getToolByName(self, 'portal_workflow', None) if wftool is not None: vars = wftool.getCatalogVariablesFor(obj) else: vars = {} w = IndexableObjectWrapper(vars, obj) ZCatalog.catalog_object(self, w, uid, idxs, update_metadata)
def catalog_object(self, obj, uid=None, **kwargs): if not isinstance(obj, self._get_forbidden_classes()): ob = IIndexableWrapper(obj) if kwargs.get('idxs'): # the first time we catalog an object we must catalog the # entire object uid = uid or "/".join(obj.getPhysicalPath()) if not uid in self._catalog.uids: del kwargs['idxs'] ZCatalog.catalog_object(self, ob, uid, **kwargs)