[Zope-CMF] Directory-based skin layers?
pw_lists at slinkp.com
Thu Apr 15 10:31:18 EDT 2004
On Wed, Apr 14, 2004 at 01:46:59PM -0700, Ricardo Newbery wrote:
> This idea is this. I would like to enable directory-based skin
> layers which would take higher precedence than the layers defined in
> portal_skins. I figure it would probably take some hacking of the
> skinning machinery. I'm not talking about an access rule that would
> reset the skin name but rather a mechanism that would acquire any
> skin layer folders in the current directory and its parents and
> prepend them to the portal_skin layer list.
> I haven't researched this yet but I'm guessing that CMF makes a
> dictionary from the portal_skin layers in order to overwrite
> references to "lower" layer objects with references to "higher" layer
> objects with the same id.
A reasonable guess, but nope :-)
Normally, if I ask for folder1.object1, acquisition does
if folder1 has an object named object1:
delegate to folder1.aq_parent
(note: that does not at all describe the implementation,
just the effective result.)
In a CMF site, eventually the chain of aq_parents will reach back to
the root PortalObject, which adds a step:
if the current skin has an object named object1:
elif I have an object named object1:
delegate to folder1.aq_parent
You can see how this is implemented by looking at
CMFCore.Skinnable.SkinnableObjectManager, which PortalObject
The __getattr__ method is what does the delegation to the object
representing the current skin (assuming self.setupCurrentSkin()
has been called).
But it's probably still not clear, as it wasn't to me,
exactly what the current skin object is, or how it looks up names.
> I figure it should be possible to hack it
> so that it can do the same with the directory-based layers.
The nice thing in the above analysis is that the "current skin object"
can be anything on which you can call getattr().
So if you can arrange that to be some class of your own, you're
halfway done. To do so, I'd replace portal_skins with either a subclass
or wrapper around the default SkinsTool implementation.
So, look at CMFCore/SkinsContainer.py and CMFCore/SkinsTool.py.
The methods of interest are getSkinByPath and/or getSkinByName.
Have these return your skin object.
It took me a while to grok the existing implementation,
because the docstrings are pretty minimal, and getSkinByPath
doesn't return anything obvious like oh, say, an instance of any
class with Skin in its name :-P Instead, it just builds a (possibly
really long) chain of acquisition-wrapped folders and returns that.
Writing a CMF tool is not hard. Just look at some simple examples,
like CMFCalendar. I highly recommend giving it a try,
tools really make development of services for CMF a lot more fun
(as compared to writing a pile of scripts in the skins).
Look! Up in the sky! It's POLYTECHNICIAN DEBUT ALBUM!
(random hero from isometric.spaceninja.com)
More information about the Zope-CMF