Although implementations of the panels_content_types() hook allows the author considerable control over the way panels handles and displays its content_types/pane_types, there remain some aspects of the process that are inaccessible to external implementations of panels' API - at least, without some really awkward hook_form_alter() calls. Nobody likes that.
The expansions to the hook_panels_content_type API that I'm considering are of two different stripes, as I'm currently thinking about them:
1. Greater control over the appearance and default values of the content type configuration form itself. At present, the API wraps the calls to the content type add/edit callbacks in such a way that implementations of the hook are incapable of circumventing anything that appears by default in the form. Some callbacks do exist that can disable certain elements, but that system needs to be made more robust.
2. The provision of some more, slightly less 'standard' callbacks in the panels_content_types() hook that make common needs easier. The primary case I've got in mind right now is pane visibility: we often want to cause certain panes to be visible or invisible, depending on a set of circumstances only known at the time of the page request.
Examples involving $user are the easiest to grok: you want to restrict buddylist visibility in a profile only to friends of the $uid to whom the profile page belongs. By implementing the visibility callback, panels will know to check for & call any visibility callbacks whenever the render process is underway. Here's an example visibility function I originally wrote for og_panels, although it didn't make it in:
/**
* Determine pane visibility based on pane settings and the user's group membership status
*
* @param string $op
* Pane visibility setting
* @param int $nid
* The nid of the group being referenced
* @return bool $visible
* Given the parameters passed in, indicates whether or not the pane should be rendered for that user
*/
function og_panels_contenttype_helper_visibility($op, $nid) {
// use static variable to somewhat reduce queries on complex og_panels pages
static $visible;
if (!is_array($visible)) {
$visible = array();
$visible['all'] = TRUE;
}
if (!isset($visible[$op])) {
global $user;
$members = array();
// @TODO this query currently excludes inactive group members, effectively placing them in the 'nonmember' grouping. Should this be changed?
$sql = "SELECT u.uid AS uid, ogu.is_admin AS admin FROM {og_uid} ogu INNER JOIN {users} u ON ogu.uid = u.uid WHERE ogu.nid = %d AND ogu.is_active = 1 AND u.status = 1 ORDER BY ogu.created DESC";
$result = db_query($sql, $nid);
while ($account = db_fetch_array($result)) {
$members[$account['uid']] = $account['admin'];
}
$visible['member'] = in_array($user->uid, array_keys($members));
$visible['nonmember'] = !$visible['member'];
$visible['admin'] = $visible['member'] ? $members[$user->uid] : FALSE;
}
return $visible[$op];
}
Being that visibility is only relevant during the render process, it's crucial that visibility functions be as lightweight as possible. The above function accomplishes that by needing to make only a single query per page request - every one of the four possibilities for the $user making the page request is determined by that query, and the results are cached via static variables. However, visibility is only one of a number of #2-style API expansions I'd like to eventually see in operation, and suggestions are welcome.
Comments
Comment #1
sdboyer commentedTwo major, major steps have been taken in this direction, with those changes available as of the beta4 API: a system of 'visibility' callbacks has been created that allows content type definitions to create their own customized logic around who/what/when/where/whatever a pane is visible, and have that logic automatically be called during the actual pane rendering process. It's as flexible as you can get.
Also, and probably even niftier in the long run, is that content types can now implement a callback that gives them full, unfettered control over the $form object used for the subforms. Full, unfettered control obviously means that you should test your changes thoroughly, as you can quite easily break panels by doing something wrong :), but better to provide the option than stick you with an interface that doesn't work for your purposes.
Keep an eye on the Plugins API subsection on the Panels 2 documentation, which is the FIRST place I'll post information about how to effectively implement these APIs in your content types. Once I have time. For now, however, I'll just post a little teaser demoing all the callbacks that can now be implemented by a given content type:
Comment #2
dwwI know the title callback for the panes is sort of in flux right now. I'd just love to be able to control, for my own panes, what shows up in the title bar on the content tab, and what shows up as the "title" in the body of the pane itself. As of a few months ago, the title bar was set via the "title callback", and the 'body title' (for lack of a better phrase) was always "No title". I'd love a callback to control both. I know you said full control over pane rendering would be a thing for panels3, but if there's anything I can do to help get limited control over these two parts in panels2, please let me know.
I searched the issue queue for an open issue specifically about this, and didn't find anything, so this seemed like the most appropriate place to discuss this. Let me know if you'd rather I bump this into its own issue.
Thanks!
-Derek
Comment #3
dwwSee #270365: Add a 'editor render callback' to pane content types and #270363: Regression: Value returned by 'title callback' not used for pane title bar for more about this pane title stuff...
Comment #4
merlinofchaos commentedWith the release of Drupal 7, Drupal 5 is no longer supported.