Possible solution to Re: [Zope-CMF] How to list objects of custom type and not of their base type?

David (Hamish) Harvey david.harvey@bristol.ac.uk
Wed, 12 Jun 2002 21:40:40 +0100


--On Wednesday, June 12, 2002 18:45:23 +0000 Florent Guillaume 
<fg@nuxeo.com> wrote:

> David (Hamish) Harvey <david.harvey@bristol.ac.uk> wrote:
>> I've created a mini-product which hotfixes PortalFolder and DynamicType
>> to  get round this. I'd appreciate comments on bugs, style, and reasons
>> why it  can't be done like this. It appears to me to work, but I haven't
>> given any  consideration to possible use cases in which this hideously
>> breaks other  things.
>>
>> http://wemrc10.wemrc.bris.ac.uk/zope.html
>
> Well your fix is a bit heavy-handed :-) as you make ObjectManager code
> know about portal_type which is a CMF concept.

The heavy-handedness depends on the point of view - less heavy handed, for 
me, than having to alter lots of templates (I might have missed a trick 
here, but I don't think so). More on that at the bottom.

I haven't touched the ObjectManager code per se, I've overridden it in 
PortalFolder. It is only in PortalFolder and subclasses that I care about 
this method of filtering, since I only expect PortalFolders to contain 
DynamicTypes. Since I *have* overridden OM methods *in* PortalFolder, 
changes in the originals would still require tracking in this fix, but I'm 
figuring they don't change that fast.

>> After all that, we can modify objectIds to check for a portal_type, and
>> if  it's available compare that with spec, otherwise use meta_type.
>
> Another bit of knowledge in ObjectManager that shouldn't be there...

As above. PortalFolder essentially recognises DynamicType derivatives and 
treats them slightly differently. OM will treat everything the same way as 
it always has.

> In the bug report I suggest this:
>
>   One more complicated solution is to derive the needed meta_type's for
>   the portal_type's in the spec, call objectValues with the restricted
>   list of meta_type's, then do the filtering above on this limited set of
>   objects.
>
> It's not as fast as your fix, but it's the cleaner I can manage (by
> handwaving) until Zope 3 :-)

Ah, until Zope 3 :-)

>> One twist - it seems that for this to work, _morphSpec has to call
>> listContentTypes with by_metatype=0. This I fear might have implications.
>
> Well yes, by_metatype=0 means you're really filtering on the customized
> Title of the type (defaulting to the Metatype), not the Metatype.

That I understood - it's required for this approach to work. Do I detect 
that we're venturing into the contentious issue of what all the different 
_types and Types are, that I've noticed has received some attention on this 
list recently? Sometime I'll find the time to go through it all and come to 
my own conclusions (or decide whose conclusions I like best, at any rate).

>> Note that this relies on the fix being in place before any items are
>> "_setObject"ed on a PortalFolder. To get round this, there's an external
>> method in the Extensions dir which will remove and re-add each object to
>> the directory using _setObject.
>
> Why not directly go patch _objects ?

_objects is an attribute. The patches only touch the things that manage 
_objects, so in essence this is the closest I can get to doing this (?)

>> It needs to be called in turn from a python script which passes it
>> context.  Is there any way for an external method to obtain the context
>> in which it  is called? I haven't worked this out.
>
> Give it a first argument of self, it will be the context. Ok, call it
> "context" then, it's not a real OO self.

Aha. That simple :-)

>> > In my sites I use a customized folder listing because of this, one that
>> > doesn't call listFolderContents. With your example I'd call
>> > objectValues('Document') and then filter by hand on portal_type.
>>
>> That would have worked, and might have fewer side effects that what I've
>> done. It would have involved modifying all the plone templates to use it
>> though, and then keeping them in sync.
>
> I hope Plone doesn't call objectValues, because it's not CMFish enough
> so could explain some bugs. OTOH seeing that listFolderContents may be
> unusable, it's understandable.

No it doesn't, it calls listFolderContents. That calls contentValues, which 
calls objectValues, which in turn uses objectIds, which is where the 
problem lies. Or rather, the problem lies in the fact that CMF assumes 
objectIds does something which it doesn't. Or even, I suppose, I use 
portal_types in a way it wasn't supposed to be used. At any rate, I think 
we have ourselves an instance of the "fragile base class" problem so 
beloved of OO detractors! This is my problem - Plone, reasonably, uses 
listFolderContents. To fix my problem I have to either

a) create a substitute for listFolderContents and change all references to 
it in the Plone templates, or
b) fix listFolderContents

Anyway - it now *is* 10, and I *still* haven't eaten :-( I'll let you know 
if I get bitten by my tinkering too deep!

Thanks again for the help and advice,
Hamish