
Upgrade Your Drupal Skills
We trained 1,000+ Drupal Developers over the last decade.
See Advanced Courses NAH, I know EnoughCtools: custom argument plugin
Parent Feed:
This time we will consider an argument plugin. Arguments are pretty similar to contexts. Actually arguments are context objects loaded from url. By default ctools provides a full set of needed arguments such as "Node: ID", "User: ID", "User: name" etc. But what if you've created a custom context? You might need to create a custom argument for your context (if you want to use your context as an argument of course). I advise you to read previous articles from "Ctools custom plugin" series such as "Ctools: custom access plugin" and "Ctools: custom context plugin". It's also required to read "Ctools: custom content type plugin" before reading this post because there I've described how to create a module integrated with ctools API which can contain ctools plugins.
For this tutorial we need a custom context (because there is no sense to copy paste default ctools argument plugins for creating default ctools context plugins - let's be creative) so I've created one: node_status. It's pretty simple and similar to default 'node' context by it provides extra node properties: 'status' and 'promote' (default node context doesn't provide them). It behaves similar to 'node' context. I mean it has a 'nid' option in settings form. Once you've entered a node id you will be able to use %argument_name:status and %argument_name:promote values. Context definition looks like:
Let's move on. Now we will create an argument plugin.
For this tutorial we need a custom context (because there is no sense to copy paste default ctools argument plugins for creating default ctools context plugins - let's be creative) so I've created one: node_status. It's pretty simple and similar to default 'node' context by it provides extra node properties: 'status' and 'promote' (default node context doesn't provide them). It behaves similar to 'node' context. I mean it has a 'nid' option in settings form. Once you've entered a node id you will be able to use %argument_name:status and %argument_name:promote values. Context definition looks like:
<?php /** * @file * * Plugin to provide a node_status context. */ /** * Plugins are described by creating a $plugin array which will be used * by the system that includes this file. */ $plugin = [ // Plugin title. 'title' => t('Node status'), // Plugin description. 'description' => t('Node status.'), // A function that will return context. 'context' => 'example_context_node_status_plugin', // Context keyword to use for // substitution in titles. 'keyword' => 'node_status', // Context machine name. 'context name' => 'node_status', // Settings form callback. 'edit form' => 'example_context_node_status_plugin_settings_form', // Default values for settings form. 'defaults' => [ 'nid' => 1, ], // Array of available context values. 'convert list' => [ 'status' => t('Node status'), 'promote' => t('Node promote'), ], // A function gets data from a given // context and returns values defined // in 'convert list' property. 'convert' => 'example_context_node_status_plugin_convert', ]; /** * Context callback. */ function example_context_node_status_plugin($empty, $data = NULL, $conf = FALSE) { // Create context object. $context = new ctools_context('node_status'); // This property should contain file name where // plugin definition is placed. $context->plugin = 'example_module.example_context_plugin.node_status'; if (empty($empty)) { // Define context data. // Variable $data can be an array or an object. // It depends on how this context is created. // If it's created by putting context directly to // a panel page then $data - array containing // settings from form. if (is_array($data) && !empty($data['nid'])) { $node = node_load($data['nid']); } // If context is created by // an argument then $data - object. if (is_object($data)) { $node = $data; } if (!empty($node)) { $context->data = $node; $context->title = $node->title; // Specify argument value - node id. $context->argument = $node->nid; } } return $context; } /** * Returns property value by property type. */ function example_context_node_status_plugin_convert($context, $type) { $result = ''; // Return node property (status or promote). if (!empty($context->data)) { $result = $context->data->{$type}; } return $result; } /** * Settings form for cookies context. */ function example_context_node_status_plugin_settings_form($form, &$form_state) { // Node id option. $form['nid'] = [ '#type' => 'textfield', '#title' => t('Node nid'), '#default_value' => $form_state['conf']['nid'], '#element_validate' => [ 'element_validate_integer_positive', ], ]; return $form; } /** * Settings form submit. */ function example_context_node_status_plugin_settings_form_submit($form, &$form_state) { // Save submitted value. $form_state['conf']['nid'] = $form_state['values']['nid']; }I won't describe what goes here because we've already discussed custom context theme last time. Just put this code into example_module/plugins/contexts/example_module.example_context_plugin.node_status.inc file. Make sure that your module file structure now looks like this one:
example_module |__ plugins | |__ content_types | | |__ example_module.example_content_type_plugin.inc | |__ access | | |__ example_module.example_access_plugin.inc | |__ contexts | |__ example_module.example_context_plugin.inc | |__ example_module.example_context_plugin.node_status.inc |__ example_module.info |__ example_module.moduleOk, finally we've got a context which we want to use as argument. For this tutorial I've created a custom page with a "node-view-page/%nid" url.
![]() |
Page with required argument |
Let's move on. Now we will create an argument plugin.
1. Create file example_module/plugins/arguments/example_module.example_argument_plugin.inc:
<?php /** * @file * * Plugin to provide an argument handler for a node_status context. */ /** * Plugins are described by creating a $plugin array which will be used * by the system that includes this file. */ $plugin = [ // Plugin title. 'title' => t('Node status argument'), // Plugin description. 'description' => t('Creates a node status context from a node ID argument.'), // Keyword. 'keyword' => 'node_status_argument', // Context builder function. 'context' => 'example_argument_plugin', ]; /** * Discover if this argument gives us the node we crave. */ function example_argument_plugin($arg = NULL, $conf = NULL, $empty = FALSE) { $context = FALSE; // If empyt it wants a generic, unfilled context. if ($empty) { $context = ctools_context_create_empty('example_module.example_context_plugin.node_status'); } else { // We can accept either a node object or a pure nid. if (is_object($arg)) { $context = ctools_context_create('example_module.example_context_plugin.node_status', $arg); } elseif (is_numeric($arg)) { $node = node_load($arg); if (!empty($node)) { $context = ctools_context_create('example_module.example_context_plugin.node_status', $node); } } } return $context; }2. Clear cache and navigate to panel page settings: arguments. Assign "Node status argument" to %nid.
![]() |
Assigned argument |
3. Navigate to panel page settings: contexts. You will see that argument provides properties from defined context.
![]() |
Context loaded from an argument |
4. Now you can use context properties for example for page title:
![]() |
Context properties are used in a page title |
Now if you open node-view-page/1, for example, you will see:
![]() |
Custom argument plugin in action |
If you unpublish a node then title will be "Status: 0 Promoted: 1". That's all.
The above is true for:
- Ctools: 7.x-1.12
- Panels: 7.x-3.8
About Drupal Sun
Drupal Sun is an Evolving Web project. It allows you to:
- Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
- Facet based on tags, author, or feed
- Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
- View the entire article text inline, or in the context of the site where it was created
See the blog post at Evolving Web
