Creating Custom Content Panes via code [Drupal 7]

For whatever reason there doesn't appear to be a lot of documenation around on defining Custom Content Panes within code.

custom_content_panes.png

All you need to do is with a custom module, create a new file called MODULE_NAME.ctools_content.inc.

In this file use the function hook_default_ctools_custom_content() to define all the custom panes you want.

The easiest way is to create your custom pane within Drupal, then use the Export tab to get the required code which will like the following:

<?php
$content 
= new stdClass();
$content->disabled FALSE;
$content->api_version 1;
$content->name 'custom_content_pane';
$content->admin_title 'Custom Content Pane';
$content->admin_description 'This appears within the admin interface for the pane.';
$content->category 'category';
$content->settings = array(
  
'admin_title' => '',
  
'title' => 'Pane title',
  
'body' => '<div>This is my custom pane</div>
'
,
  
'format' => 'full_html',
  
'substitute' => 1,
);
?>

This then gets added in to the hook_default_ctools_custom_content() like so:

<?php

function MODULE_NAME_default_ctools_custom_content() {
  
$export = array();

  $content = new stdClass();
  
$content->disabled FALSE;
  
$content->api_version 1;
  
$content->name 'custom_content_pane';
  
$content->admin_title 'Custom Content Pane';
  
$content->admin_description 'This appears within the admin interface for the pane.';
  
$content->category 'category';
  
$content->settings = array(
    
'admin_title' => $content->admin_title// Add the admin title to the settings array so that it appears in the pane form.
    
'title' => 'Pane title',
    
'body' => '<div>This is my custom pane</div>
  '
,
    
'format' => 'full_html',
    
'substitute' => 1,
  );
  
$export[$content->name] = $content// Add the pane to the $export array

  return $export;
}
?>

And that is all you need. The $content->name variable has to be unique, so it is best to use $export[$content->name] rather than $export[] to stop any unexpected behaviour.

Update:

You'll also need to tell Ctools what version of the plugin you are using, so in your MODULE_NAME.module file, add the following:

<?php
function MODULE_NAME_ctools_plugin_api($module$api) {
  if (
$module == "ctools_custom_content" && $api == "ctools_content") {
    return array(
"version" => "1");
  }
}
?>

Comments

The main reason it isn't documented specifically is that the 'bulk export' module can generate all this code for you, and it works the same way for any CTools exportable type.

That would certainly explain it. Would still be worth having it documented as if you don't enabled the bulk export module you have no way of finding out.

Hi James,

Trying to find out how to implement my custom content contained in Bulk Export output, I googled "hook_default_ctools_custom_content" (with quotes) expecting to get the usual millions of helpful references. I got 8 with your page at the top and the only page that wasn't github source or something.

Unfortunately there is no guidance as to where to place the file or what to put in mymodule.module, if anything.

I created the file mymodule.ctools_content.inc and put it in sites/mysite/modules/mymodule/ and also sites/mysite/modules/mymodule/plugins/content_types. I included the necessary code in mymodule.module - function mymodule_ctools_plugin_directory() "if ($owner == 'ctools' && $plugin_type == 'content_types' ... return "plugins/$plugin_type".

But whatever I did, and believe me I tried several variations, I could not get Panels to show anything but "There are no custom content panes" under "Manage custom content". I should mention that I had created my content through the GUI and it showed here before which is how I was able to export it. But I then deleted it after exporting it so I could have it "in Code". And yes I did all the usual stuff - Clear Cache, etc..

Eventually I gave up and ultimately got my Custom Content working under the guidance of Letharion's post: http://drupal.stackexchange.com/questions/33336/how-does-one-create-a-ne....

But I can't help wondering how to get that Bulk Export Custom Content code working ....

Cheers,
Chris

Did you remember to add the:

$export[$content->name] = $content; // Add the pane to the $export array

after your export code? Sounds like you did everything as you were supposed to. The inc file goes in to the module directory.

Although saying that, I may have missed a rather important part of code out which I have now added to the bottom of the post.

Yesssss! It was the 'rather important part of code' that fixed it. Thank you!

As for '$export[$content->name] = $content', Bulk Export does that for you except it calls it $contents, thus: '$contents['my_content'] = $content;'

Incidentally I posted this same question, but referencing your article, at http://drupal.stackexchange.com/questions/77941

I suppose this will all be mostly irrelevant when Drupal 8 comes out next month since it looks as if Panels functionality will be effectively replaced by Twig/SCOTCH/Spark. No sooner does one get to grips with something than it's replaced by something else. Oh well.

Glad to hear that worked. Have added the fix to your stackexchange post.

Haven't had a chance to look at D8 although did have a brief look at Spark early on.