API allowing programmatic determination of available layout types

sdboyer - February 28, 2008 - 19:08
Project:Panels
Version:5.x-2.x-dev
Component:Code
Category:task
Priority:normal
Assigned:sdboyer
Status:closed
Description

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

AttachmentSize
display_edit.inc.patch1.64 KB
panels.module.patch1.14 KB

#1

sdboyer - March 4, 2008 - 13:10

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.
  • Content Type Grouping (& Context - this is where it gets a little off the beaten track. But there's also plenty of examples - numerous modules use the technique of marking certain content types as being platforms for instantiating their functionality. OG is one, Casetracker is another, and so is Nodeprofile; when well-implemented, these modules provide functions for determining whether a given nid is from a content type that is part of their module's grouping. It seems to me that providing direct support for configuring a set of available panel layouts is a possibility that should be considered. Maybe require the name of a record from the variables table that contains an array of content types as one of the arguments passed into $scope?
  • 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:

    • Global Settings - probably primarily useful for sites with less complex permissions systems, this would simply allow an admin to restrict all access to a given layout, unless that user was a member of some uber role.
    • User/uid-based (possibly AKA roles-based) - I think this is where we really start treading in treacherously complex waters, but restrictions by role, or even per-user, is at least another possibility.
    • 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

    sdboyer - March 8, 2008 - 12:40
    Status:patch (code needs review)» active (needs more info)

    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

    sdboyer - March 8, 2008 - 14:49

    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

    merlinofchaos - March 13, 2008 - 17:14

    Yes, they should follow the same pattern if possible.

    #5

    moshe weitzman - May 3, 2008 - 01:31

    Any chance you can get back to this, sdboyer?

    #6

    sdboyer - May 3, 2008 - 01:44

    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

    sdboyer - May 10, 2008 - 05:09
    Status:active (needs more info)» patch (code needs review)

    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

    AttachmentSize
    228089-7-allowed_layouts_api.patch15.43 KB

    #8

    sdboyer - May 10, 2008 - 05:09
    Assigned to:Anonymous» sdboyer

    #9

    sdboyer - May 10, 2008 - 21:50
    Status:patch (code needs review)» fixed

    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.

    AttachmentSize
    228089-9-allowed_layouts_api.patch20.46 KB

    #10

    sdboyer - May 10, 2008 - 23:02

    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

    Anonymous (not verified) - May 24, 2008 - 23:11
    Status:fixed» closed

    Automatically closed -- issue fixed for two weeks with no activity.

     
     

    Drupal is a registered trademark of Dries Buytaert.