This is an overview (not detailed howto) of an implementation:
Catalog tool done similarly to the reference_catalog from Archetypes. The most essential parts:
from Products.ZCatalog.ZCatalog import ZCatalog
class MemberdataCatalog(UniqueObject, ZCatalog):
implements(IMemberdataCatalog)
...
security.declareProtected(ManageZCatalogEntries, 'catalog_object')
def catalog_object(self, obj, uid=None, idxs=[],
update_metadata=1, pghandler=None):
w = obj
if not IIndexableObject.providedBy(obj):
wrapper = component.queryMultiAdapter((obj, self), IIndexableObject)
if wrapper is not None:
w = wrapper
ZCatalog.catalog_object(self, w, w and str("/".join(w.getPhysicalPath())), idxs,
update_metadata, pghandler=pghandler)
(with all GenericSetup things, also can be done similarly to Archetypes)
Subscribers for IPrincipalCreatedEvent, IPrincipalDeletedEvent, IConfigurationChangedEvent
(the latter one needs event.context.class._name_ in ('UserDataConfiglet', 'PersonalPreferencesPanel', 'UserDataPanel') to be handled - unfortunately, Plone has no specific events for profile data changes). See PAS on how those work and which parameters
event handlers receive.
A view /memberdata/username for the catalog to address and reindex those users. The "username" done by bobo traverse and returns an wrapped user with properties,
needed for indexes and metadata.
The http://plone.org/products/collective.examples.userdata is a good guide how to actually extend the user profile.
Apart from that, an adapter is needed
class IndexableAdapter(EnhancedUserDataPanelAdapter):
implements(IIndexableObject)
adapts(IMemberData, IMemberdataCatalog)
def __init__(self, context, catalog):
self.context = context
self.userid = context.getId()
self.catalog = catalog
def getPhysicalPath(self):
return make_physical_path(self.userid) # path to the view, which "fakes" an object
def __getattr__(self, name):
""" Proxing attribute accesses. """
return getattr(self.context, name)
# Specific indexer
def SearchableTextIntra(self):
...
Here EnhancedUserDataPanelAdapter has been derived and extended from UserDataPanelAdapter.
The IMemberdataCatalog is the interface of the catalog.
It is important to put everything into metadata, even width/height of the portrait,
because using .getObject() made the whole thing hundreds of times (!) slower.
The group memberships were handled separately, because there are no events, which
signify changes in the groups, needed to reindex some or all memebrs.