def _reindex(ob, texts=False): catalog = find_catalog(ob) if catalog is None: return # Will be true for a mailin test trace # XXX reindexing the 'path' index can be removed once we've # removed the last ACLChecker spelled in catalog queries from the # code; this is the "old" way of doing security filtering. path_index = catalog['path'] path_index.reindex_doc(ob.docid, ob) # In some cases changing the workflow state of an object can change its # ranking in text search. if texts: text_index = catalog['texts'] text_index.reindex_doc(ob.docid, ob) # if the object is folderish, we need to reindex it plus all its # subobjects' 'allowed' index entries recursively; each object's # allowed value depends on its parents in the lineage allowed_index = catalog.get('allowed') if allowed_index is not None: for node in postorder(ob): if hasattr(node, 'docid'): allowed_index.reindex_doc(node.docid, node)
def mothball_community(community): catalog = find_catalog(community) tags = find_tags(community) def get_docid(doc): return catalog.document_map.docid_for_address(resource_path(doc)) # Unindex all documents, remove top level tools # Make copy of items so we're not mutating a BTree while traversing it for name, tool in list(community.items()): if name == 'members': # We probably want to hang on to historical membership data continue for doc in postorder(tool): # includes tool in traversal log.info("Removing %s", resource_path(doc)) docid = get_docid(doc) tags.delete(docid) catalog.unindex_doc(docid) del community[name] log.info("Removing tags") docid = get_docid(community) tags.delete(docid) catalog.unindex_doc(docid) community.description = 'This community has been archived.' community.text = render('templates/archived_community_text.pt', {'settings': get_current_registry().settings}) community.archive_status = 'archived' community.default_tool = None log.info("Finished removing content: %s", resource_path(community))
def recent_items(self): if self._recent_items is None: community = find_interface(self.context, ICommunity) if community is not None: stmt = """SELECT docid from pgtextindex WHERE community_docid='%s' AND content_type not in ('IInvitation', 'ICalendar', 'ICalendarLayer', 'ICalendarCategory', 'IBlog', 'ICommunityRootFolder', 'IWiki') ORDER BY modification_date DESC LIMIT 20""" catalog = find_catalog(self.context) index = catalog['texts'] docids = index.get_sql_catalog_results(stmt % community.docid) self._recent_items = [] for docid in docids: path = catalog.document_map.address_for_docid(docid[0]) try: model = find_resource(self.context, path) except KeyError: continue if not has_permission('view', model, self.request): continue try: adapted = getMultiAdapter((model, self.request), IGridEntryInfo) except ComponentLookupError: continue self._recent_items.append(adapted) return self._recent_items
def evolve(root): catalog = find_catalog(root) mimetype_index = catalog['mimetype'] search = ICatalogSearch(root) docid_for_addr = catalog.document_map.docid_for_address count, docids, resolver = search(interfaces=[ICommunityFile], mimetype={ 'operator': 'or', 'query': [ 'application/x-download', 'application/x-application', 'application/binary', 'application/octet-stream', ] }) for docid in docids: doc = resolver(docid) mimetype = mimetypes.guess_type(doc.filename)[0] if mimetype is not None and mimetype != doc.mimetype: addr = resource_path(doc) print "Updating mimetype for %s: %s" % (addr, mimetype) doc.mimetype = mimetype mimetype_index.reindex_doc(docid_for_addr(addr), doc)
def __init__(self, context, request=None): # XXX request argument is not used, is left in for backwards # compatability. Should be phased out. self.context = context self.catalog = find_catalog(self.context) if request is not None: warnings.warn("Creating CatalogSearch with request is deprecated.", DeprecationWarning, stacklevel=2)
def evolve(context): """ Upgrades required for new Image Drawer functionality. """ # Add IImage marker to instances of ICommunityFile which are images. catalog = find_catalog(context) search = ICatalogSearch(context) cnt, docids, resolver = search(interfaces=[ICommunityFile]) for docid in docids: obj = resolver(docid) if obj is None: continue # Work around catalog bug obj._init_image() if obj.is_image: print "Image: %s" % resource_path(obj) catalog.reindex_doc(obj.docid, obj) # Convert WikiPages to Folders so they can contain attachments cnt, docids, resolver = search(interfaces=[IWikiPage]) for docid in docids: obj = resolver(docid) if obj is None: continue # Work around catalog bug print "Convert wiki page to folder: %s" % resource_path(obj) Folder.__init__(obj) catalog.reindex_doc(obj.docid, obj)
def evolve(site): """ Upgrade pgtextindex """ catalog = find_catalog(site) index = catalog['texts'] index.upgrade()
def evolve(root): former_id = None # Create lazily, in case we don't need it profiles = find_profiles(root) search = ICatalogSearch(root) catalog = find_catalog(root) creators = catalog['creator']._fwd_index.keys() modifiers = catalog['modified_by']._fwd_index.keys() userids = set(creators) | set(modifiers) for userid in userids: if userid not in profiles: if former_id is None: former_id = make_unique_name(profiles, 'formeruser') print "Creating profile for former user content:", former_id former_profile = create_content( IProfile, firstname='Former', lastname='User' ) profiles[former_id] = former_profile count, docids, resolver = search(creator=userid) for docid in docids: doc = resolver(docid) print "Updating 'creator' for", resource_path(doc) doc.creator = former_id count, docids, resolver = search(modified_by=userid) for docid in docids: doc = resolver(docid) print "Updating 'modified_by' for", resource_path(doc) doc.modified_by = former_id
def recent_items(self): if self._recent_items is None: community = find_interface(self.context, ICommunity) if community is not None: stmt = """SELECT docid from pgtextindex WHERE community_docid='%s' AND content_type not in ('IInvitation', 'ICalendar', 'ICalendarLayer', 'ICalendarCategory', 'IBlog', 'ICommunityRootFolder', 'IWiki') ORDER BY modification_date DESC LIMIT 20""" catalog = find_catalog(self.context) index = catalog['texts'] docids = index.get_sql_catalog_results(stmt % community.docid) self._recent_items = [] for docid in docids: path = catalog.document_map.address_for_docid(docid[0]) try: model = find_resource(self.context, path) except (KeyError, TypeError): continue if not has_permission('view', model, self.request): continue try: adapted = getMultiAdapter((model, self.request), IGridEntryInfo) except ComponentLookupError: continue self._recent_items.append(adapted) return self._recent_items
def get_container_batch( container, request, batch_start=0, batch_size=20, sort_index=None, reverse=False, permission="view", filter_func=None, interfaces=None, ): if "batch_start" in request.params: batch_start = int(request.params["batch_start"]) if "batch_size" in request.params: batch_size = int(request.params["batch_size"]) if sort_index: catalog = find_catalog(container) index = catalog[sort_index] # XXX this is not part of ICatalogIndex, but it happens to work # for most indexes. It might be useful to expand ICatalogIndex. sort_func = index.discriminator else: sort_func = None entries = [] # [(sort key, name, item)] for name, item in container.items(): if interfaces: # item must provide at least one of the given interfaces for iface in interfaces: if iface.providedBy(item): break else: continue if permission: if not has_permission(permission, item, request): continue if filter_func: if not filter_func(name, item): continue if sort_func is not None: sort_key = sort_func(item, None) else: sort_key = None entries.append((sort_key, name, item)) entries.sort() if reverse: entries.reverse() page_entries = entries[batch_start : batch_start + batch_size] info = { "entries": [item for _, _, item in page_entries], "batch_start": batch_start, "batch_size": batch_size, "batch_end": batch_start + len(page_entries), "total": len(entries), } _add_link_data(info, container, request) return info
def reindex_batch(args, site): catalog = find_catalog(site) addr = catalog.document_map.address_for_docid new_index = catalog['new_texts'] to_index = new_index.to_index indexed = new_index.indexed l = new_index.n_to_index offset = l - len(to_index) batch = [] for i in xrange(min(BATCH_SIZE, len(to_index))): batch.append(to_index[i]) for i, docid in enumerate(batch): to_index.remove(docid) indexed.add(docid) path = addr(docid) if path is None: continue try: doc = find_model(site, path) except KeyError: log.warn("No object at path: %s", path) continue log.info("Reindexing (%d/%d) %s", i + offset + 1, l, path) new_index.index_doc(docid, doc) deactivate = getattr(doc, '_p_deactivate', None) if deactivate is not None: deactivate()
def __init__(self, context, request): self.context = context self.request = request self.username = authenticated_userid(request) self.path = resource_path(context) self.catalog = find_catalog(context) self.tags = find_tags(context)
def evolve(root): catalog = find_catalog(root) mimetype_index = catalog['mimetype'] search = ICatalogSearch(root) docid_for_addr = catalog.document_map.docid_for_address count, docids, resolver = search( interfaces=[ICommunityFile], mimetype={ 'operator': 'or', 'query': [ 'application/x-download', 'application/x-application', 'application/binary', 'application/octet-stream', ]} ) for docid in docids: doc = resolver(docid) mimetype = mimetypes.guess_type(doc.filename)[0] if mimetype is not None and mimetype != doc.mimetype: addr = resource_path(doc) print "Updating mimetype for %s: %s" % (addr, mimetype) doc.mimetype = mimetype mimetype_index.reindex_doc(docid_for_addr(addr), doc)
def user_tagged_content(event): if ITagAddedEvent.providedBy(event): request = get_current_request() context = getattr(request, 'context', None) if context is None: return events = find_events(context) if not events: return site = find_site(context) catalog = find_catalog(context) path = catalog.document_map.address_for_docid(event.item) tagged = find_resource(site, path) if tagged is None: return profile_id = event.user if profile_id in (None, 'None'): return profile = site['profiles'][profile_id] info = _getInfo(profile, tagged) if info is None: return if info['content_type'] == 'Community': info['flavor'] = 'tagged_community' elif info['content_type'] == 'Person': info['flavor'] = 'tagged_profile' else: info['flavor'] = 'tagged_other' info['operation'] = 'tagged' info['tagname'] = event.name events.push(**info)
def mothball_community(community): catalog = find_catalog(community) tags = find_tags(community) def get_docid(doc): return catalog.document_map.docid_for_address(resource_path(doc)) # Unindex all documents, remove top level tools # Make copy of items so we're not mutating a BTree while traversing it for name, tool in list(community.items()): if name == 'members': # We probably want to hang on to historical membership data continue for doc in postorder(tool): # includes tool in traversal log.info("Removing %s", resource_path(doc)) docid = get_docid(doc) tags.delete(docid) catalog.unindex_doc(docid) del community[name] log.info("Removing tags") docid = get_docid(community) tags.delete(docid) catalog.unindex_doc(docid) community.description = 'This community has been archived.' community.text = render('templates/archived_community_text.pt', { 'settings': get_current_registry().settings}) community.archive_status = 'archived' community.default_tool = None log.info("Finished removing content: %s", resource_path(community))
def evolve(root): former_id = 'formeruser' profiles = find_profiles(root) search = ICatalogSearch(root) catalog = find_catalog(root) creators = catalog['creator']._fwd_index.keys() modifiers = catalog['modified_by']._fwd_index.keys() userids = set(creators) | set(modifiers) for userid in userids: if userid not in profiles: if former_id not in profiles: workflow = get_workflow(IProfile, 'security') former_id = make_unique_name(profiles, 'formeruser') print "Creating profile for former user content:", former_id former_profile = create_content(IProfile, firstname='Former', lastname='User') profiles[former_id] = former_profile workflow.initialize(former_profile) workflow.transition_to_state(former_profile, None, 'inactive') count, docids, resolver = search(creator=userid) for docid in docids: doc = resolver(docid) print "Updating 'creator' for", resource_path(doc) doc.creator = former_id count, docids, resolver = search(modified_by=userid) for docid in docids: doc = resolver(docid) print "Updating 'modified_by' for", resource_path(doc) doc.modified_by = former_id
def user_tagged_content(event): if ITagAddedEvent.providedBy(event): request = get_current_request() context = getattr(request, "context", None) if context is None: return events = find_events(context) if not events: return site = find_site(context) catalog = find_catalog(context) path = catalog.document_map.address_for_docid(event.item) tagged = find_resource(site, path) if tagged is None: return profile_id = event.user if profile_id in (None, "None"): return profile = site["profiles"][profile_id] info = _getInfo(profile, tagged) if info is None: return if info["content_type"] == "Community": info["flavor"] = "tagged_community" elif info["content_type"] == "Person": info["flavor"] = "tagged_profile" else: info["flavor"] = "tagged_other" info["operation"] = "tagged" info["tagname"] = event.name events.push(**info)
def evolve(root): former_id = 'formeruser' profiles = find_profiles(root) search = ICatalogSearch(root) catalog = find_catalog(root) creators = catalog['creator']._fwd_index.keys() modifiers = catalog['modified_by']._fwd_index.keys() userids = set(creators) | set(modifiers) for userid in userids: if userid not in profiles: if former_id not in profiles: workflow = get_workflow(IProfile, 'security') former_id = make_unique_name(profiles, 'formeruser') print "Creating profile for former user content:", former_id former_profile = create_content( IProfile, firstname='Former', lastname='User' ) profiles[former_id] = former_profile workflow.initialize(former_profile) workflow.transition_to_state(former_profile, None, 'inactive') count, docids, resolver = search(creator=userid) for docid in docids: doc = resolver(docid) print "Updating 'creator' for", model_path(doc) doc.creator = former_id count, docids, resolver = search(modified_by=userid) for docid in docids: doc = resolver(docid) print "Updating 'modified_by' for", model_path(doc) doc.modified_by = former_id
def evolve(root): former_id = None # Create lazily, in case we don't need it profiles = find_profiles(root) search = ICatalogSearch(root) catalog = find_catalog(root) creators = catalog['creator']._fwd_index.keys() modifiers = catalog['modified_by']._fwd_index.keys() userids = set(creators) | set(modifiers) for userid in userids: if userid not in profiles: if former_id is None: former_id = make_unique_name(profiles, 'formeruser') print "Creating profile for former user content:", former_id former_profile = create_content(IProfile, firstname='Former', lastname='User') profiles[former_id] = former_profile count, docids, resolver = search(creator=userid) for docid in docids: doc = resolver(docid) print "Updating 'creator' for", resource_path(doc) doc.creator = former_id count, docids, resolver = search(modified_by=userid) for docid in docids: doc = resolver(docid) print "Updating 'modified_by' for", resource_path(doc) doc.modified_by = former_id
def move_content(root, src, dst, wf_state): try: context = find_resource(root, src) except KeyError: print >> sys.stderr, "Source content not found: %s" % src sys.exit(-1) try: dest_folder = find_resource(root, dst) except KeyError: print >> sys.stderr, "Destination folder not found: %s" % dst sys.exit(-1) src_community = find_community(context) catalog = find_catalog(root) assert catalog is not None users = find_users(root) assert users is not None if src_community is not None: move_header = ('<p><em>This was originally authored ' 'in the "%s" community.</em></p>' % src_community.title) else: move_header = '' src_folder = context.__parent__ name = context.__name__ log.info("Moving %s", resource_path(context)) for obj in postorder(context): if hasattr(obj, 'docid'): docid = obj.docid catalog.document_map.remove_docid(docid) catalog.unindex_doc(docid) del src_folder[name] if (context.creator != 'admin' and users.get_by_id(context.creator) is None): # give the entry to the system admin log.warning("User %s not found; reassigning to admin", context.creator) context.creator = 'admin' if name in dest_folder: name = make_unique_name(dest_folder, context.title) dest_folder[name] = context for obj in postorder(context): if hasattr(obj, 'docid'): docid = obj.docid catalog.document_map.add(resource_path(obj), docid) catalog.index_doc(docid, obj) if wf_state is not None: wf = get_workflow(get_content_type(context), 'security', context) wf.transition_to_state(context, None, wf_state) if hasattr(context, 'text'): context.text = "%s\n%s" % (move_header, context.text)
def evolve(context): catalog = find_catalog(context) for path, docid in catalog.document_map.address_to_docid.items(): if _exists(context, path): continue print "Unindexing:", path catalog.unindex_doc(docid)
def reindex_content(obj, event): """ Reindex a single piece of content (non-recursive); an IObjectModifed event subscriber """ catalog = find_catalog(obj) if catalog is not None: path = resource_path(obj) docid = catalog.document_map.docid_for_address(path) catalog.reindex_doc(docid, obj)
def __init__(self, context, request=None): # XXX request argument is not used, is left in for backwards # compatability. Should be phased out. self.context = context self.catalog = find_catalog(self.context) if request is not None: warnings.warn('Creating CatalogSearch with request is deprecated.', DeprecationWarning, stacklevel=2)
def unindex_content(obj, docids): """ Unindex given 'docids'. """ catalog = find_catalog(obj) if catalog is not None: for docid in docids: catalog.unindex_doc(docid) catalog.document_map.remove_docid(docid)
def manage_tags_view(context, request): page_title = 'Manage Tags' api = TemplateAPI(context, request, page_title) tagger = find_tags(context) userid = context.__name__ error = '' old = '' new = '' catalog = find_catalog(context) address_for_docid = catalog.document_map.address_for_docid def get_doc(docid): path = address_for_docid(docid) return find_resource(context, path) if 'form.rename' in request.POST and 'old_tag' in request.POST: old_tag = request.POST['old_tag'] new_tag = request.POST['new_tag'] # check that tag contains only valid characters if re_tag.match(new_tag) is None: error = u'Value contains characters that are not allowed in a tag.' old = old_tag new = new_tag else: docids = tagger.getItems(tags=[old_tag], users=[userid]) to_update = {} for tagob in tagger.getTagObjects(items=docids, users=[userid]): if tagob.name == old_tag: name = new_tag else: name = tagob.name to_update.setdefault(tagob.item, []).append(name) for docid in docids: tagger.update(item=docid, user=userid, tags=to_update.get(docid, [])) catalog.reindex_doc(docid, get_doc(docid)) if 'form.delete' in request.POST and 'todelete' in request.POST: old_tag = request.POST['todelete'] for docid in tagger.getItems(tags=[old_tag], users=[userid]): tagger.delete(item=docid, user=userid, tag=old_tag) catalog.reindex_doc(docid, get_doc(docid)) if tagger is None: tags = () else: tags = list(tagger.getTags(users=(context.__name__, ))) tags.sort() return dict( api=api, my_tags=tags, error=error, old=old, new=new, )
def evolve(context): catalog = find_catalog(context) profiles = find_profiles(context) for profile in profiles.values(): if profile.country not in countries.as_dict: print ('Evolving profile %s country from "%s" to "XX"' % (profile.__name__, profile.country)) profile.country = 'XX' catalog.reindex_doc(profile.docid, profile)
def manage_tags_view(context, request): layout = request.layout_manager.layout layout.page_title = 'Manage Tags' api = TemplateAPI(context, request, layout.page_title) tagger = find_tags(context) userid = context.__name__ error = '' old = '' new = '' catalog = find_catalog(context) address_for_docid = catalog.document_map.address_for_docid def get_doc(docid): path = address_for_docid(docid) return find_resource(context, path) if 'form.rename' in request.POST and 'old_tag' in request.POST: old_tag = request.POST['old_tag'] new_tag = request.POST['new_tag'] # check that tag contains only valid characters if re_tag.match(new_tag) is None: error = u'Value contains characters that are not allowed in a tag.' old = old_tag new = new_tag else: docids = tagger.getItems(tags=[old_tag], users=[userid]) to_update = {} for tagob in tagger.getTagObjects(items=docids, users=[userid]): if tagob.name == old_tag: name = new_tag else: name = tagob.name to_update.setdefault(tagob.item, []).append(name) for docid in docids: tagger.update(item=docid, user=userid, tags=to_update.get(docid, [])) catalog.reindex_doc(docid, get_doc(docid)) if 'form.delete' in request.POST and 'todelete' in request.POST: old_tag = request.POST['todelete'] for docid in tagger.getItems(tags=[old_tag], users=[userid]): tagger.delete(item=docid, user=userid, tag=old_tag) catalog.reindex_doc(docid, get_doc(docid)) if tagger is None: tags = () else: tags = list(tagger.getTags(users=(context.__name__,))) tags.sort() return dict( api=api, my_tags=tags, error=error, old=old, new=new, )
def evolve(context): catalog = find_catalog(context) profiles = find_profiles(context) for profile in profiles.values(): if profile.country not in countries.as_dict: print('Evolving profile %s country from "%s" to "XX"' % (profile.__name__, profile.country)) profile.country = 'XX' catalog.reindex_doc(profile.docid, profile)
def del_tags(context, request, values): """ Delete the specified tags. """ username = authenticated_userid(request) path = model_path(context) catalog = find_catalog(context) docid = catalog.document_map.docid_for_address(path) tags = find_tags(context) for tag in values: tags.delete(item=docid, user=username, tag=tag)
def evolve(site): """Convert date indexes to GranularIndex. """ catalog = find_catalog(site) for name in ['creation_date', 'modified_date', 'content_modified', 'start_date', 'end_date', 'publication_date']: index = catalog[name] if not isinstance(index, GranularIndex): print "Converting field index '%s' to GranularIndex..." % name catalog[name] = convert_to_granular(index)
def handle_content_removed(obj, event): """ IObjectWillBeRemovedEvent subscriber. """ catalog = find_catalog(obj) if catalog is not None: path = resource_path(obj) num, docids = catalog.search(path={'query': path, 'include_path': True}) unindex_content(obj, docids) cleanup_content_tags(obj, docids)
def evolve(site): """Optimize CatalogKeywordIndexes. Requires zope.index 3.6.3. """ catalog = find_catalog(site) for name, idx in catalog.items(): if isinstance(idx, CatalogKeywordIndex): print "Optimizing keyword index '%s'..." % name idx.optimize()
def get_index_type(args, site): """Get the type name of the current index. """ catalog = find_catalog(site) index = catalog['texts'] if isinstance(index, KarlPGTextIndex): return 'pg' elif isinstance(index, CatalogTextIndex): return 'zope' else: return 'other (%s)' % type(index)
def evolve(root): search = ICatalogSearch(root) catalog = find_catalog(root) index = catalog['mimetype'] for old_type, new_type in ie_types.items(): cnt, docids, resolver = search(mimetype=old_type) for docid in docids: doc = resolver(docid) print "Adjusting mimetype for %s" % resource_path(doc) doc.mimetype = new_type index.reindex_doc(docid, doc)
def del_tags(context, request, values): """ Delete the specified tags. """ username = authenticated_userid(request) path = resource_path(context) catalog = find_catalog(context) docid = catalog.document_map.docid_for_address(path) tags = find_tags(context) for tag in values: tags.delete(item=docid, user=username, tag=tag) catalog.reindex_doc(docid, context)
def __call__(self, docid): site = self.context.site catalog = find_catalog(site) if catalog is None: raise ValueError('No catalog') path = catalog.document_map.address_for_docid(docid) if path is None: raise KeyError(docid) doc = find_resource(site, path) community = find_community(doc) return community and community.__name__ or None
def _modify_community(obj, when): # manage content_modified on community whenever a piece of content # in a community is changed community = find_interface(obj, ICommunity) if community is not None: community.content_modified = when catalog = find_catalog(community) if catalog is not None: # may not be wired into the site yet index = catalog.get('content_modified') if index is not None: index.index_doc(community.docid, community)
def evolve(context): today = datetime.utcnow() catalog = find_catalog(context) profiles = find_profiles(context) for profile in profiles.values(): days = randint(170, 190) expiration_date = today + timedelta(days=days) if profile.password_expiration_date is None: print('Setting profile %s password expiration date to "%s"' % (profile.__name__, expiration_date)) profile.password_expiration_date = expiration_date
def evolve(context): today = datetime.utcnow() catalog = find_catalog(context) profiles = find_profiles(context) for profile in profiles.values(): days = 180 expiration_date = today + timedelta(days=days) if profile.password_expiration_date is None: print('Setting profile %s password expiration date to "%s"' % (profile.__name__, expiration_date)) profile.password_expiration_date = expiration_date
def ResovlerFactory(context): catalog = find_catalog(context) address = catalog.document_map.address_for_docid def resolver(docid): path = address(docid) if path is None: return None try: return find_resource(context, path) except KeyError: return None return resolver
def evolve(site): """Convert profile's '_pending_alerts' to an Accumulator. """ catalog = find_catalog(site) search = ICatalogSearch(site) count, docids, resolver = search( interfaces={'query': [IProfile]}) for docid in docids: doc = resolver(docid) alerts = doc._pending_alerts if not isinstance(alerts, Accumulator): doc._pending_alerts = Accumulator(list(alerts))
def evolve(site): catalog = find_catalog(site) profiles = find_profiles(site) text_index = catalog['texts'] for profile in profiles.values(): if profile.security_state != 'inactive': profile._p_deactivate() continue print "Reindexing profile: ", profile.__name__ text_index.reindex_doc(profile.docid, profile)