Create Custom Visibility Rules in Panels Using Ctools Access Plugins

Panels comes with a great feature where you can control the visibility of individual panel panes. Visibility rules are useful when you need to show or hide a pane based off some criteria. You can add a rule by clicking on the cogwheel on the pane and then click on “Add new rule” within the Visibility rules section.

Fig 1.1

The default options are fine for simple configuration. But sometimes you’ll need to write a bit of code to implement complex requirements. To handle this functionality Panels utilises the Ctools access plugin. So if you need to build custom visibility rules then just write your own access plugin.

Today I’ll show you how to create a basic access plugin for those times when the default options won’t cut it.

We’ll create a plugin which hides the body if the string “hide body field” appears in the title. I understand this functionality is basic but it’s a good way to demonstrate how access plugins work.

Basic PHP knowledge is required and I’ll assume you know how to create a custom module.

Step 1: Implement “hook_ctools_plugin_directory”

The first thing you need to do is let Ctools know where the plugin directory in the module is. Add the following bit of code into your custom module.

/**
 * Implements hook_ctools_plugin_directory().
 */
function title_hide_ctools_plugin_directory($module, $plugin) {
  if ($module == 'ctools' && !empty($plugin)) {
    return "plugins/$plugin";
  }
}

This will tell Ctools to search in the plugins/access directory within the module.

Double check and make sure that the function name is correct. If it’s not, then the plugin simply won’t appear and you will waste time trying to figure out why it’s not working only to realise it’s because you spelt the function name wrong.

It happens to the best of us.

Step 2: Define Plugin

Go into plugins/access and create a file title_hide.inc. This file is where the actual plugin is stored.

Copy the following bit of code into the top of the file:

/**
 * @file
 * Plugin to check if the title has configured string.
 */

$plugin = array(
  'title' => t('Title string'),
  'description' => t('Checks if title has configured string in title.'),
  'callback' => 'title_hide_ctools_access_check',
  'default' => array('negate' => 0),
  'summary' => 'title_hide_ctools_access_summary',
  'settings form' => 'title_hide_ctools_access_settings',
  'required context' => new ctools_context_required(t('Node'), 'node'),
);

The $plugin is used to define the plugin, let’s look at the array in more detail:

  • title and description: These are used in the Panels interface so make them descriptive.
  • callback: This is the actual function which will be used. It should return a TRUE or FALSE.
  • default: This sets the default value for the access settings form.
  • summary: A summary is always displayed in the visibility rules and selection rules section.
  • settings form: This is used to define a settings form for the plugin.
  • required context: This tells Panels which context are required. In this case it’s the node context.

Step 3: Create Settings Form

The purpose of this plugin is to search for a string within the title. It wont make sense to hard code the search term. We’ll create a settings form and make it configurable.

Add the following bit of code into the plugin:

/**
 * Settings form for the 'title hide' access plugin.
 */
function title_hide_ctools_access_settings($form, &$form_state, $conf) {
  $form['settings']['keyword'] = array(
    '#title' => t('Keyword'),
    '#type' => 'textfield',
    '#description' => t('Title field will be searched for entered string.'),
    '#default_value' => $conf['keyword'],
    '#required' => TRUE,
  );
  return $form;
}

All we’re doing is defining a single text field called “Keyword”. We don’t have to define a validate or submit handler, Ctools handles this for us. The saved or default value can be retrieved from the $conf variable.

Step 4: Create Plugin Summary

The summary callback is used to display some summary text if the access plugin is being used. Here’s an example of the summary on a visibility rule:

Fig 1.5

To implement this, add the code below into the plugin:

/**
 * Provide a summary description.
 */
function title_hide_ctools_access_summary($conf, $context) {
  $replacement = array('@keyword' => $conf['keyword']);
  return t('Checks if "@keyword" appears in title.', $replacement);
}

Step 5: Create Callback Function

Last but not least, in the $plugin array we specified title_hide_ctools_access_check as the callback, let’s now add that function in.

Copy the bit of code below:

/**
 * Check for access.
 */
function title_hide_ctools_access_check($conf, $context) {
  // Return false if context is not set.
  if (empty($context) || empty($context->data)) {
    return FALSE;
  }

  $node = $context->data;

  if (strpos($node->title, $conf['keyword']) !== FALSE) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}

The code is pretty basic. At the end of it we always return something; TRUE or FALSE. An important part is getting access to the node object and you can do this via the $context variable, $node = $context->data;. Values configured in the title_hide_ctools_access_settings form can be retrieved from the $conf variable.

Step 6: Use as Visibility Rule

So we’ve built the plugin and now we need to implement it into the actual body field. I’ll assume you’ve already got Panels setup.

1. Go into one of your panel variants and click on the Content page.

Fig 1.0

2. Click on the cogwheel on the Body field and then click on “Add new rule”.

Fig 1.1

3. From the pop-up click on “Title string” and click on Next.

Fig 1.2

4. Remember in step 3 we implemented title_hide_ctools_access_settings, this allows us to make the search keyword configurable and not hard coded. Enter in the keyword which will be used. For this example, I’ll enter in “hide title”.

Also go ahead and check the “Reverse (NOT)” checkbox, then click on Save.

The reason why we check “Reverse (NOT)” is because by default if an access plugin returns TRUE, then the field – body field – is displayed. But we want to hide the field if it returns TRUE, so it needs to be reversed. We could change the logic in code but it’ll make the plugin too specific.

Fig 1.3

5. Now go and create an article and if you enter in “test article hide title” in the title field, then the Body field shouldn’t be displayed.

Fig 1.4

Summary

Most access plugins are basic but they offer a tremendous amount of flexibility when building complex pages. If you had to hide or show a field based on a custom criteria, you would need to write a lot of code. Best of all, access plugins are reusable so if you’re using Panels across your site, you can reuse them as long as you’ve developed them in a generic way.

You can find the complete module that we created on GitHub.

FAQs

Q: My access plugin doesn’t appear in the “Add visibility rule” modal pop-up.

If your plugin isn’t appearing it’s because Ctools can’t find it and there could be a few reasons. First, make sure your module which ships the plugin is enabled. This happens more often than you think. Second, double check and make sure you’ve implemented hook_ctools_plugin_directory properly.

Ivan Zugec

About Ivan Zugec

Ivan is the founder of Web Wash and spends most of his time consulting and writing about Drupal. He's been working with Drupal for 10 years and has successfully completed several large Drupal projects in Australia.

3 thoughts on “Create Custom Visibility Rules in Panels Using Ctools Access Plugins”

Leave a Comment

You have to agree to the comment policy.