API allowing programmatic determination of available layout types
| Project: | Panels |
| Version: | 5.x-2.x-dev |
| Component: | Code |
| Category: | task |
| Priority: | normal |
| Assigned: | sdboyer |
| Status: | closed |
Hi Earl -
Here's the patch that oughtta at least kick-start us towards making it possible for callers of panels_edit_layout(), _panels_edit_layout(), OR panels_choose_layout() to pass in a parameter determining which of the installed layouts should be available. I feel like I've missed something here, because it appears there's hardly anything to it; I've verified that providing an array of strings with internal names of layout types does indeed restrict the available types to only those, AND that leaving out the parameter means that it displays all installed layout types.
I don't know if panels_choose_layout() gets called from anywhere besides _panels_edit_layout(). I initially put the new code in _panels_edit_layout, which works fine for the standard layout editing screen, but if that form ever gets called from somewhere else, it would be without any selectable layouts at all. So I put the layout-determining code into the form function itself, but then I also noticed that there's a panels_change_layout() function which bypasses my code entirely. To handle both cases from one place would require changing something inside of panels_get_layouts(), and I think that starts getting us into the realm of storing the layout permissions data somewhere more permanent and picking it up as needed - more along the lines of your panels_cache system for content. I'd be happy to write something that goes that route if need be, but this system does work...so here 'tis.
cheers
Sam
| Attachment | Size |
|---|---|
| display_edit.inc.patch | 1.64 KB |
| panels.module.patch | 1.14 KB |

#1
I've been working on a UI that allows an administrator to set more permanent values for available layouts, especially in the context of looking through moshe's og_panels work. Creating the form itself really isn't very hard (90% of the work's already been done in panels_choose_layout(), panels_change_layout()); the much bigger question is one of scope. Actually, that's most of the difference between the functions; I've stuck the function that initiates the process of building a layout-access-control-form in around line 415 of panels.module (calling it panels_edit_available_layouts) , immediately after the other three functions that deal with panel editing/layout editing. What sets my function apart is that it does not receive a $display parameter; in its place, it receives a parameter I call scope.
The solution I wrote above restricting available layouts on the basis of an additional parameter to panels_edit_layout() works fine, but it's not a scalable solution. Rather than effectively requiring module developers to 'roll their own' system for governing which layouts are available to which people/on which panels, it makes more sense to me that that be something that panels takes care of internally. Maximum efficiency, minimum confusion and mess. Which is why we end up at the question of scope: as far as I can think through it, if we're providing an API for controlling access to layouts, then the API needs to be able to accommodate as wide a range of configurations as possible. Thus far, here's what I've been able to think up in terms of possible scopes, which in my mind correspond roughly with your contexts, but not exactly:
- Node (& Context) - The set of layout restrictions being selected will apply only to a given node ID, or rather, a given node ID's context. I at first thought this would be fairly limited under most circumstances (how likely would it be that you create a panel to replace a given node and then DON'T choose the layout yourself???). However, thinking of it in terms of node context opens the pool of possibilities, as og_panels demonstrates: multiple displays are non-admin creatable, all of which get their location and other settings from their associated nid's node context.
- Content Type (& Context) - would require a new context be written, I think?)
- Here, the layout restrictions are applied to anything that derives its node context from a given content type. Thinking in terms of og_panels again, this is quite useful; in fact, I'm likely to implement it in my current work, as the site I'm building employs several different group types.All three of those could, and (for the sake of maintaining a clean, manageable UI) possibly ONLY should be implemented via remote module calls to the appropriate panels functions. No need for the admin/panels pages to go about setting highly granular permissions for every possible module in one place...that'd make /admin/user/access look like a masterpiece of efficient design. However, there are two other types of scopes I can think of:
It wouldn't make much sense to open global settings up to external modules, which means that global settings should be implemented through something like /admin/panels/layouts, but it's not so clear with the users. The best case I can actually see granularity at the level of users/roles arises, once again, from groups: As a group admin, it might be helpful to be able to specify which of my group roles, or the individuals in my group, were able to create which panel layouts. Then again...we're REALLY just talking about LAYOUTS, it doesn't really seem worth all the effort to control something that's effectively presentational.
Anyway, I just wanted to lay out what my thoughts were on possible directions/issues regarding the creation of a UI. The more I look back over this, the more it feels like serious overkill (and please, don't hesitate for a second to tell me so!). I just have trouble putting a problem down before I've worked through all the dimensions of it that I can think of.
#2
Update on this - I've finished off an initial version of the edits to this. At this point, the way I've implemented the available_layouts form functions, they cannot be accessed directly via any of the existing panels UI. Rather, they present an API that allows modules implementing their own panels setup to create variables table entries by simply appending '_available_layouts' to a string passed in to the function; these variables are arrays containing available layout selections. At the moment, the code is still really preliminary, which will be especially obvious if you have a look at the relevant validation and submission functions in display_edit.inc (should these be in common.inc instead?).
Since I'm doing work on this primarily from the perspective of getting the necessary functionality for og_panels up and running, the only way to actually have a gander at what I've put together is to do it via og_panels. For that, see #225501: Panels2/OG integration - new argument and context, and download the second patch in comment #5.
#3
Dunno why I didn't see this before: just noticed how panels_common_get_allowed_types() uses a finalized version of pretty much the same system of module-based variable setting that I'd begun scrapping together for layouts. I can switch over my code to conform with the general pattern you've used there, if you want.
#4
Yes, they should follow the same pattern if possible.
#5
Any chance you can get back to this, sdboyer?
#6
Your timing couldn't be better, I'm just in the midst of a panels kick. Sure, I'll add it to the list of things to be done for beta4.
Sorry, I've just been really swamped with this big project, it keeps ballooning out of control.
#7
Ooookie doke - after seeing how ugly attempts to squeeze all the necessary parameters to do this properly into a fourth parameter for panels_edit_layout() would get, I decided to go OO instead. So, this little piece of the panels API has the (dubious?) honor of being the very first non-data storage piece of the API to be written in OO. It certainly won't be the last.
The panels_allowed_types class (which, btw, I'm strongly considering just moving over into panels.module to avoid potential problems with common.inc not being loaded into the current scope) is built with the intention that client modules which are seriously implementing the panels API will extend the class, beginning with creating a save() method that defines a process for saving allowed layouts data however the client module wants to save it.
The new API features are pretty thick with documentation (it's gotta be at least 1:1 doxy docs vs. code in there, with doxy nearly comin out ahead), so a lot of the explanation about how to implement this should be pretty much plug-and-chug. I have tested it from the panels_edit_layout() end and verified that a properly formed panels_allowed_layouts object does limit the available layouts to those specified by $obj->layout_settings. The only question is whether or not the panels_common_set_allowed_layouts() form does what it's supposed to do. I didn't have a sandbox for testing it immediately handy, but I'll get to that presently (unless someone beats me to it).
I'm not committing the code just yet, as I'm waiting for merlin to get a chance to look at it, first. However, it/some variant of it should be in -dev pretty soon. In the meantime, Moshe, if you want to give this a whirl and see how it works for you, I've attached a patch (against the current -dev) which'll allow you to give it a spin.
Here's a pastebin-ed amalgam of the changes in the patch, too: http://drupal.pastebin.com/m106069cc
#8
#9
OK, I've been through and pretty thoroughly debugged this code as well as updating the documentation, so I'm committing it for beta4. If you want it before then, Moshe...erm, well, I can't promise that -dev is entirely stable, but here's an updated patch that details all the final changes. It's against -dev, so you'd need to work it out against beta3.
#10
Oh, and - documentation on the class is available at http://doxy.samboyer.org/panels2/classpanels__allowed__layouts.html. That's most of what's been changed, and what isn't on that page is available via the links to other functions, especially the @see links.
#11
Automatically closed -- issue fixed for two weeks with no activity.