Writing panels integration

I'm working on a project where I need to get some of my custom content into Panels. Having the Panels interface to manage things is obviously a huge boon, but I wanted to do more than create Drupal blocks- I wanted the same kind of integration that modules like Views and CCK are using.

Poking around, I didn't find much information on how to actually write your own Panels integration, so after a few fits and starts, I just started from block.inc as an example and then have abstracted it here.
I wanted to do this in a fairly simple way- a basic definition function and then a set of functions that pass these definitions off to theme functions. I'm making an example out of my code for people to use- hopefully it is useful to see how to set this up.

First we're going to define what the items are that will be used as panes in Panels. This is a custom function, not a Panels function.

/**
* Defines the panel content for this module.
* @return array
* array has a key which will be used as a function call and a title
*/
function mymod_panels_content_define() {
$items = array(
'mymod_item_1' =>; t('This is pane one'),
'mymod_item_2' =>; t('This is pane two'),
);
return $items;
}

Now we need to declare the theme functions that will be used. Obviously these are rather simple for demonstration purposes, but you get the idea. Note that you would name these in relationship to your declarations above. Here is the first pane:

/**
* display the content for item 1
* @param array $conf
* @return string
* html return
*/
function theme_mymod_item_1($conf) {
return "my module item 1 theme function output";
}

And the second- again, here is where you would add your custom functions.

/**
* display the content for item 2
* @param array $conf
* @return string
* html return
*/
function theme_mymod_item_2($conf) {
return "my module item 2 theme function output";
}

Now we need to tell Panels about our code. This declares what functions are responsible for handling the Panels callbacks. These are Panels functions.

/**
* Callback function to supply a list of content types.
* @return array
*/
function mymod_panels_panels_content_types() {
$items['mymod panes'] = array(
'title' =>; t('My Module panes'),
'content_types' =>; 'mymod_panels_admin_content_types',
'title callback' =>; 'mymod_panels_admin_title',
'add callback' =>; 'mymod_panels_admin_add',
'render callback' =>; 'mymod_panels_content',
);
return $items;
}

Now that Panels knows about our code, we tell it how to handle the content types. We're going to get the items that we declared first and then assign them a few additional pieces of information to make them appear in the right places in the admin interface.

/**
* Return all block content types available.
* @return array
*/
function mymod_panels_admin_content_types() {
$types = array();
foreach (mymod_panels_content_define() as $id =>; $title) {
$info = array(
'title' =>; $title,
'category' =>; array(t('My Module panes')),
'icon' =>; drupal_get_path('module', 'mymod_panels') .'/images/mymod.gif',
'id' =>; $id,
);
$types["mymod_panels-$id"] = $info;
}
return $types;
}

When an admin adds our pane, we need to add some additional information to the pane so that we can access it during the rendering phase. In the above function, we keyed the array data with the module and function data so we can pull it out easily. Now we just need to put that data into a form:

/**
* Returns the form for a new block.
*/
function mymod_panels_admin_add($id, $parents, $conf = array()) {
list($conf['module'], $conf['delta']) = explode('-', $id, 2);
$form['module'] = array(
'#type' =>; 'value',

'#value' =>; $conf['module'],

);
$form['delta'] = array(
'#type' =>; 'value',
'#value' =>; $conf['delta'],
);
return $form;
}

Now that we've added this data into the form, it is passed through to the render phase. In this example, to render the pane, we are doing something simple- just pass the call to a coresponding theme function- one of the ones we declared above.

/**
* call the content to generate for the pane in question
* calls a theme(module_name_pane_name, $conf);
* @param array $conf
* @return object
*/
function mymod_panels_content($conf) {
$function = $conf['module'] .'_'. $conf['delta'];
$block = new stdClass();
$block->;content = theme("$function", $conf);
return $block;
}

Finally, we just need a function that declares the title of the pane to Panels:

/**
* Returns the administrative title for a type.
* @param array $conf
*/
function mymod_panels_admin_title($conf) {
$panels = mymod_panels_content_define();
return $panels[$conf['delta']];
}

Now you've got a fast way to integrate your custom content into Panels. There might be easier/faster ways to do this, but I haven't found an examples to build from. You can download the example file here as well: mymod_panels.php

Add a new comment