Mayo 13, 2013
estebanvalerioh
Si estamos trabajando con Paneles, puede ser muy útil tener plugins propios que generen contenido que pudiéramos agregar a una región específica de nuestro paneles.
A continuación crearemos un plugin para Ctools de clase “Content Type” utilizando context de panels, esto es diferente a los Content Type creados por el Entity.
- Estructura de los directorios.
 
Para mantener los estándares, nos aseguramos de tener los directorios de la siguiente forma:
custom_module/
custom_module/custom_module.info
custom_module/custom_module.module
custom_module/plugins/
custom_module/plugins/content_types/
custom_module/plugins/content_types/nombre_del_plugin.inc- Indicarle al módulo Ctools de nuestro plugin.
 
Manteniendo la estructura de directorios mencionada, copiamos en custom_module.module la siguiente función.
/**
 * Implements hook_ctools_plugin_directory().
 */
function custom_module_ctools_plugin_directory($module, $plugin) {
 if ($module == 'ctools' && !empty($plugin)) {
 return "plugins/$plugin";
 }
}- Indicarle al módulo de Panels que incorpore nuestro plugin.
 
Siempre en nuestro archivo custom_module.module, copiamos la siguiente función.
/**
 * Implement hook_ctools_plugin_api().
 */
function custom_module_ctools_plugin_api($module, $api) {
 if ($module == 'panels_mini' && $api == 'panels_default') {
 return array('version' => 1);
 }
 if ($module == 'page_manager' && $api == 'pages_default') {
 return array('version' => 1);
 }
}- Definición de nuestro plugin.
 
Al inicio de nuestro archivo nombre_del_plugin.inc, creamos un arreglo con las características principales de nuestro plugin y es aquí donde indicamos que nuestro plugin requiere de un contexto para poder ser utilizado, en este caso el contexto será de tipo NODE.
$plugin = array(
 'title' => t('Titulo del Plugin'),
 'description' => t('Breve descripción.'),
 'single' => TRUE,
 'content_types' => 'nombre_del_plugin',
 'render callback' => 'nombre_del_plugin_render',
 'required context' => array(
    new ctools_context_required(t('Node'), 'node'),
  ), 
 'edit form' => 'nombre_del_plugin_edit_form',
 'category' => array(t('Custom Plugin'), -9),
 'defaults' => array(),
);Agregamos el context al panel, como en la siguiente imagen:

En este punto vamos a poder ver nuestra categoría Custom Plugin en la lista de opciones para agregar, como en la siguiente imagen:
En la siguiente imagen podemos ver la opción de selección del Tipo de Contenido de Ctools “Titulo del Plugin”, pero debemos tener en cuenta que esta opción estará disponible si y solo sí el panel tiene un context de tipo NODE asociado.

- Función de edición/configuración.
 
Cuando agregamos nuestro plugin como contenido de una región de un Panel, podemos mostrarle al usuario un formulario donde puede ingresar datos, los cuales posteriormente vamos a utilizar para desplegar el contenido con el que estemos trabajando. Eso lo hacemos de la siguiente forma
function nombre_del_plugin_edit_form($form, &$form_state) {
 $conf = $form_state['conf'];
 $form['config_number'] = array(
 '#type' => 'textfield',
 '#title' => t('Ingrese un número'),
 '#size' => 20,
 '#description' => t('Número para mostrar al usuario.'),
 '#default_value' => !empty($conf['config_number']) ? $conf['config_number'] : '',
 '#prefix' => '<div class="clear-block no-float">',
 '#suffix' => '</div>',
 );
 return $form;
}
function nombre_del_plugin_edit_form_submit($form, &$form_state) {
 foreach (element_children($form) as $key) {
 if (!empty($form_state['values'][$key])) {
 $form_state['conf'][$key] = $form_state['values'][$key];
 }
 }
}El formulario de configuración creado anteriormente sería similar al presentado en la siguiente imagen.

- Desplegando el contenido.
 
Esta función, se encarga de generar el bloque que va a renderizar el contenido con el que estamos trabajando. En la variable $conf encontraremos los valores definidos en nuestra función de edición, y en la variable $args, los valores que pueden venir en la URL definida de nuestro Panel.
function nombre_del_plugin_render($subtype, $conf, $args, $context) {
  $numero = !empty($conf['config_number']) ? $conf['config_number'] : 0;
  if (empty($context) ) {
    return;
  }
  $context = array_shift($context);
  if (isset($context->data) && empty($context->data)) {
    return;
  }
  $node = $context->data;
  $block = new stdClass();
  $block->title = "Mi primer plugin";
  $block->content = "Contenido de mi bloque, el número ingresado es: $numero y el título del nodo es: {$node->title}.";
  return $block;
}En la variable $context contendrá la información proveniente del contexto del panel, que es este caso será la información del Nodo.
La forma de desplegar el contenido va a depender de la configuración que cada usuario tenga con el css y html. Ejemplo:

Espero les sea de utilidad.

