Ticket #9284 (closed PLIP: wontfix)
Allow views to override skin layer elements easily
Reported by: | MatthewWilkes | Owned by: | MatthewWilkes |
---|---|---|---|
Priority: | minor | Milestone: | 4.0 |
Component: | Unknown | Version: | |
Keywords: | Cc: | regebro@…, plip-advisories@… |
Description (last modified by alecm) (diff)
Proposer: Matthew Wilkes
Seconder: Alec Mitchell
Motivation
At the root of a plone site a CMF skin based template "foo" would be rendered in preference to a browser view named "foo". On sub pages this is inverted. The practical upshot of this is that it isn't possible to reliably override a skin element with a view without writing special-casing the root.
Proposal
Change the precedence of the traverser that runs on the Plone site root to delegate to views in preference to attributes with an origin in a CMF Skin. The precedence would hence become:
1. ``Real'' attributes 2. (context, request) multiadapters 3. CMF Skin attributes 4. Acquired attributes
Implementation
- Create a new implementation of DefaultPublishTraverse and register it on the root of the Plone site.
- Add a prominent UI warning to skin layers when a resource is being overriden by a view.
- Modify the logic on the "currently active" marker for the Find tab in the ZMI of portal_skins to handle the new logic
Assumptions
It is assumed that there will be a sensible way to quickly and reliably discern between "real" attributes and those provided by a skin. There is magic involved here which I am not 100% familiar with as yet. Also, it's assumed that nobody is relying on this inconsistent behaviour for useful functionality, it seems more of a let than anything else.
Risks
- Existing code that delegates to an identically named view will continue to work, but any special casing that might be in the delegating scripts to handle the site root will not.
- The portal_skins UI may become more confusing for integrators who are mixing the two methods of customisation, or who inherit a site from a third party.
- Code that traverses manually to the name will get the original version, not the overridden one, but this is true of all browser views.
- The more complex traverser could slow down site requests by requiring another condition be matched
Change History
comment:3 Changed 7 years ago by pupq
There's a use case that is fairly common that I'm not sure people would handle with your solution:
We have a template that is site-wide (perhaps a CMF skin, in custom/ or on-disk, or perhaps a z3-wired view). We want to override that template in a particular section of our site.
The classic Zope-ish way to do that would be to put the special version of that template in that folder, in content space.
If acquired objects are the least-preferred, this will remove the ability to do that.
Do we have yet an easily-understood way for an average integrator to override a template in a part of a site? This is a fairly common problem.
If we have a solution here that will allow this, then this seems -0 for integrators. If this removes this case and we don't have an alternate solution, this seems -1 for integrators.
comment:4 Changed 7 years ago by MatthewWilkes
Joel,
There are two cases here, the one that I think you're talking about is where integrators copy a CMF skin template to a folder to customise it for a subtree. This will absolutely still work as there is no browser view with that name registered.
The other one that you seem to be talking about is customising a z3 view by copying into a subtree. This doesn't work in the current setup. You only get the customised version in the context that it's copied into, acquired is already at the bottom of the chain.
This just changes it to be consistent, so skin-layer elements don't cause that gotcha on the root of the site.
Matt
comment:5 Changed 7 years ago by pupq
Matthew -- Thanks. It was the first case I wanted to make sure we protect (I understand that many developers don't like the idea of templates living in content space, and I can sympathize. But integrators do have lots of cases where they need to swap out templates locally, and this is the only real, workable solution that is widely understood at the moment).
So, then, then seems +1 -- loses nothing useful, and gets us consistency.
That said: *is* there an appropriate solution for the very-commonly-requested "how can I change the footer for this folder [or other z3-view-handled-skin-object] of my site?" That's a very common request--"placeful" templates are a big deal for many (esp academic or larger-corporate) sites. There seem to be several possible emerging strategies, but none that seem obvious to me as the Right Way That You Approve Of. (This isn't the place to answer this question, I know--just something for the framework team to keep in mind).
comment:6 Changed 7 years ago by alecm
As a developer, the way I would solve this problem would be to apply a marker to the request (i.e. a z3 skin) upon traversal of the desired folder. Then I could register custom versions of views for that skin. It may make sense to package this technique into an add-on product, though it still wouldn't allow in-ZODB customization without a significant effort (i.e. integration of skin selection into portal_view_customizations). Alternatively , this sort of thing could be done with a locally registered version of the portal_view_customizations utility.
Ususally, CSS is enough for me though. :-) Locally customized templates spread throughout the site can be a tremendous nightmare for upgrades, etc.
comment:7 Changed 7 years ago by MatthewWilkes
You could probably make a local p_v_c in an add-on product without much effort. The problem would be that it would be damn-near impossible to exportimport in a sensible way.
comment:8 Changed 7 years ago by regebro
If this should be changed for consistency, then the ordering in the root should change, so the ordering is:
- Real attributes
- (context, request) multiadapters
- Acquired attributes
- CMF Skin attributes
Everything else would be confusing and unzopeish.
comment:10 Changed 7 years ago by erikrose
Clearing Owner field of 4.0 PLIPs so we can use it to mean "implementor". (Many of these owners were automatically assigned from choosing a Component that had a default owner.)
comment:12 Changed 7 years ago by rossp
FWT vote +1. The only reason I use skin objects any more is because I can't easily override skin objects with views, so I think this would be great.
comment:13 Changed 7 years ago by davisagli
FWT vote +1 assuming you can actually pull this off. :-p
Please do some benchmarks to see how this affects the performance of things like AT edit screens that rely heavily on CMF skin items, and include the results in your notes when you submit for review.
comment:14 Changed 7 years ago by raphael
FWT vote: +1
But please bring this up on zope-cmf as well. I'd consider this essentially a bug that should be fixed in CMF (if people there agree)
comment:15 Changed 7 years ago by calvinhp
FWT Vote: +1 consistency is always good
comment:16 Changed 7 years ago by esteele
Approved by FWT vote.
comment:19 Changed 7 years ago by alecm
comment:20 Changed 7 years ago by esteele
- Status changed from assigned to closed
- Resolution set to wontfix
After discussion, the Framework Team feels that this is a bug in CMF and should be fixed there and instead of being patched in Plone.
This is an important fix for consistency. I think it belongs in CMF though as this issue comes from the interaction between Zope traversal semantics and CMF's skins implementation and affects all CMF sites.
Working around the magic getattr on the portal (from SkinnableObjectManager) is going to be quite tricky. You will likely need retrieve the object and then look at it's physical path or real container (aq_parent(aq_inner(object))) to determine if it is a native attribute or from the skins. It may make sense to register this custom traverser directly on the SkinnableObjectManager class rather than the site root, since there may theoretically be other objects in the portal which look up skins directly. Also, I think we need to override standard traversal, not just publish traversal; so that e.g. path expressions within templates work consistently.