Local sites in Five =================== Intro ----- Zope 3 has a concept of local sites and site managers. They allow one to locally override component registrations and have components and their configuration be persisted in the ZODB as well as managed through the web interface. Five 1.5 supports two distinct and slightly incompatible versions of local site support. The first one, (here known as "old" sites) was introduced in Five 1.3 and is based on Zope 3.2s site implementation. But the site implementation in Zope 3.2 was overly complicated, and for 3.3 it was refactored, and Five 1.5 contains support for this new local site support as well (known as "new" sites). For documentation of how to use local sites, see the Zope 3.3 documentation. This document is mostly about how the implementation of the old sites work, and how to migrate from Five 1.3 and 1.4. Migration from old sites to new sites ------------------------------------- New sites are based on Zope 3.3s new site managers and persistent component registries. Old sites are based on specific Five implementation of site managers, and keeps utilities in a folder called "utilities". They are used basically the same, but they are created differently, and also, when you look up a utility with getUtility or queryUtility, in old sites, the utility will have an acquicition context, while in the new sites it will not. Setting up the site ................... The old setup of a site was done by marking the class of the site as a possible site with five:localsite, and then either manually through the ZMI or programmatically through enableLocalSiteHook(site) turn it into a site. The new setup involves calling enableSite(site) and createing and setting a site manager. The simplest way to do this manually is to go to the "components.html" view of the object you want to make a site, and press the "Make site" button. The easist way to do this programmatically, is to look up the "components.html" view on the site, and calling view.makeSite(): components_view = queryMultiAdapter((self.context, self.request), Interface, 'components.html') components_view.makeSite() As any ObjectManager can be a site there is no longer any need to specially mark the class as being a possible site. Registering local utilities ........................... The old usage was to get the site manager, either throgh adapting with IFiveUtilityRegistry(site) or by calling getSiteManager(). You could then register the utilities with sitemanager.registerUtility(interface, utility) The new way is to call getSiteManager().registerUtility(object, provided). Note that in the old way, the first parameter is the interface name, and the second the actual utility object, but in the new way, it is the other way around. Migrating the actual sites .......................... Go to the object of the site, and add "manage_site.html" to the URL to open the old site management view. There you have a button "Migrate to Five.component". Press it to migrate the site. Experimental forwards compatibility ................................... If you have software using the old sites, and software using the new sites, there is sligthly experimental support to make software expecting new sites to work with old sites. Nothing is promised with this, as it is largely untested. The best thing to do is without a doubt to convert your old site software and your old sites to use new sites. Old site implementation details =============================== The rest of this document documents the details of the old site implementation. Everything from here on concerns only the old implementation and is of mainly hysterical interest. By default, Zope 3 has a global site which is configured through ZCML. It provides the fallback for all component look-up. Local sites are typically set during traversal, when the traverser encounters an ``ISite`` object. The last encountered ``ISite`` wins. Component look-up will cascade through all the sites in the hierarchy and fall back to the global site where it can finally fail. Five also supports local sites, however by default only local utilities. Local adapters, such as ZODB-based views, could be supported with a custom implementation of the local site manager and local adapter registry. This is not the focus of local sites in Five, though. Turning possible sites into sites --------------------------------- Five uses the same technique as Zope 3 for determining local sites: sites are found during URL traversal. However, since the Zope 2 ZPublisher doesn't emit the necessary events by default, Five needs to set a ``BeforeTraverse`` hook on site objects. Setting this hook needs to be done an object-per-object basis and can be performed through the ``manage_site.html`` browser page. This view operates on ``IPossibleSite`` objects (in other words, objects that *can* be sites but aren't yet). It sets the traversal hook on the object and then marks it with the ``ISite`` interface to indicate that it is a real site now, not just a possible site. Note that unlike the Zope 3 equivalent of this view, it does not set the site manager to site; it is assumed that the site already knows how to get its site manager. Custom site implementations --------------------------- Anything can be a site, there are no restrictions (sites don't have to be folders, for examples). Sites can also be nested. For all the Component Architecture cares, every object in your URL graph could be a site. The only requirement are two interfaces: ``IPossibleSite`` Objects that can potentially be turned into a site need to provide this interface. That requires them to have a ``setSiteManager()`` and ``getSiteManager()`` method for setting and getting the local site manager of that site. The site manager is the registry that takes care of local component look-up. ``IFiveSiteManager`` This interface is a slight extension of the ``IServiceService`` or ``ISiteManager`` interface, respectively (the former in Zope X3 3.0, the latter in later versions). It defines the API of a local site manager that is to be used in a Five environment. The site's ``getSiteManager()`` method should return an object providing this interface. Five's default site manager ---------------------------- If you want to instantly make your custom class an ``IPossibleSite`` implementation, you can use a default mix-in class from Five, e.g.:: class MySite(OFS.Folder, Products.Five.site.localsite.FiveSite): pass This default implementation of ``IPossibleSite`` features a site manager implementation that knows how to register and look-up local utilities. It does so by adapting the site to ``IFiveUtilityRegistry``. The default adapter for this local utility registry simply stores the utilities in a standard OFS Folder on called ``utilities`` on the site object. You probably want to exchange that simple behaviour with something that works better in your application. You can do so by plugging in your own utility registry adapter, e.g.:: All this implementation needs to do is comply with the ``IFiveUtilityRegistry`` interface, which essentially means the standard utility look-up methods like ``queryUtility()``, ``getUtilitiesFor()``, etc. Turning existing classes into possible sites -------------------------------------------- If you cannot or do not want to modify existing classes to mix in the ``FiveSite`` class, you can also use a structured monkey patch via ZCML:: This makes ``MyClass`` an ``IPossibleSite`` and sticks ``FiveSite``'s ``getSiteManager()`` and ``setSiteManager()`` methods on the class as well. You can also tell it to use a different site implementation's methods for the monkey patch:: Just make sure that this class implements ``IPossibleSite``.