Mayo 04, 2014
omers
En Drupal es comun trabajar con módulos que usan “definiciones de configuracion” (configuration presets), tales como Panels, Context o el mas famoso modulo contribuido hasta la version 7 de Drupal, ahora ya en el core de Drupal 8, Views.
Con los configuration presets podemos crear, editar, borrar y exportar tantas configuraciones o estructuras queramos.
Pero que pasa cuando los módulos mencionados no cubren nuestras necesidades y nos vemos forzados de crear nuestros propios módulos, que tengan configuraciones o estructuras y de esta forma poder distribuirlo. No te preocupes hoy les explicare como hacerlo usando el gran poder como lo es el modulo Chaos Tool Suite (ctools).
Ctools en un modulo que nos provee una serie de API’S y herramientas para ayudarnos en el desarrollo de nuestros módulos, y en nuestro caso ocuparemos la funcionalidad export y de esta manera haremos que los valores de nuestras configuraciones o modelos de datos en nuestra DB, se conviertan en objetos exportables y así poder manipularlos a nuestra conveniencia.
- Agregar dependencias.
Como todos sabemos cuando necesitamos la funcionalidad de algún otro módulo contribuido en nuestro módulo personalizado necesitamos agregarlo como dependencia para no tener problemas en el futuro, a continuación un ejemplo
name = MIMODULO
description = This module assign a user as fan of a team in Soccer League.
package = Demo
core = 7.x
dependencies[] = ctools
- Generar modelo de datos.
Necesitamos tener la tabla en la que almacenaremos estos datos, para crear una table te recomiendo que le des un vistazo al articulo Como crear tablas para nuestros módulos personalizados en Drupal 7 el cual lo describe con mas detalle, solo que a la hora de implementar nuestro hook_schema vamos a notar un par de nuevas cosas.
/**
* Implements hook_schema().
*/
function MIMODULO_schema() {
$schema['team'] = array(
'description' => 'Teams that can be assigned to a user',
'fields' => array(
'team_id' => array(
'description' => 'The primary identifier for the team.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
//This param is to tell ctools that is not be necessary exported to code
'no export' => TRUE),
'name' => array(
'description' => 'The name of the Team',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => ''),
'description' => array(
'description' => 'Brief descriptive text of the Team',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => ''),
),
'primary key' => array('team_id'),
//Add some data for exportable plugin more information ctools/help/export.html
'export' => array(
'key' => 'name',
'key name' => 'Team Name',
'primary key' => 'team_id',
'default hook' => 'favorite_team_info',
'api' => array(
'owner' => 'favorite_team',
'api' => 'favorite_team',
'minimum_version' => 1,
'current_version' => 1,
),
),
);
return $schema;
}
Acá podemos ver algunos atributos nuevos, de inicio podemos notar el atributo de ’no export’ en el identificador primario team_id, puesto que no nos interesa exportar el identificador, debido a que este cambia de una base de datos a otra.
También podemos darnos cuenta que agregamos nuevos datos a nuestro schema para poder darle la funcionalidad de exportación, este es el caso de nuestra nueva sección export, en la cual le damos algunas indicaciones como la llave primaria de nuestros objetos, el titulo legible de nuestros objetos, el hook que se debe invocar para encontrar los objetos exportables. Además los datos de api con el fin de no tener problemas cuando trabajemos con futuras versiones de nuestro proyecto.
Para información mas detallada puedes revisar la documentación localizada dentro del modulo (ctools/help/export.html).
Los cambios a nuestro esquema se pueden hacer aun si la tabla ya esta creada, porque el proceso de exportación leerá la ultima definición y no es necesario que esto se haya hecho al mismo momento de la creación de la tabla en la base de datos.
- Definir directorio de exportación.
Una vez que en nuestro schema hemos indicado a ctools que nuestra tabla será exportable, tenemos que decirle en que directorio vamos a implementar nuestro plugin esto lo conseguiremos implementando el hook hook_ctools_plugin_directory()
/**
* Implements hook_ctools_plugin_directory().
*/
function MIMODULO_ctools_plugin_directory($module, $plugin) {
if ($plugin == 'export_ui') {
//assign the folder of ctools plugins files relative to module root
return 'plugins/export_ui';
}
}
Lo anterior implica que debe existir en nuestro modulo el directorio plugins y el directorio export_ui dentro de este.
- Implementar plugin de exportación.
Es hora de implementar nuestro plugin, inicialmente lo que debemos de hacer es crear un archivo con extensión .inc en el directorio que definimos anteriormente en nuestro caso plugins/export/miarchivo_export_ui.inc en el cual le daremos algunas indicaciones a nuestro modulo.
$plugin = array(
// The name of the table as found in the schema in hook_install. This
// must be an exportable type with the 'export' section defined.
'schema' => 'team',
// The access permission to use. If not provided it will default to
// 'administer site configuration'
'access' => 'administer site configuration',
//Menu settings
'menu' => array(
'menu prefix' => 'admin/config/people',
'menu item' => 'team',
// Title of the top level menu. Note this should not be translated,
// as the menu system will translate it.
'menu title' => 'Teams',
// Description of the top level menu, which is usually needed for
// menu items in an administration list. Will be translated
// by the menu system.
'menu description' => 'Administer favorite teams for users.',
),
// These are required to provide proper strings for referring to the
// actual type of exportable. "proper" means it will appear at the
// beginning of a sentence.
'title singular' => t('team'),
'title singular proper' => t('Team'),
'title plural' => t('teams'),
'title plural proper' => t('Teams'),
// This will provide you with a form for editing the properties on your
// exportable, with validate and submit handler.
//
// The item being edited will be in $form_state['item'].
//
// The submit handler is only responsible for moving data from
// $form_state['values'] to $form_state['item'].
//
// All callbacks will accept &$form and &$form_state as arguments.
'form' => array(
'settings' => 'favorite_team_ctools_export_ui_form',
'validate' => 'favorite_team_ctools_export_ui_form_validate',
'submit' => 'favorite_team_ctools_export_ui_form_submit',
),
);
/**
* Implements hook_form_alter().
*/
function favorite_team_ctools_export_ui_form(&$form, &$form_state) {
$team = $form_state['item'];
$form['description'] = array(
'#type' => 'textfield',
'#title' => t('Short description of the team'),
'#default_value' => isset($team->description) ? $team->description : $team->description,
'#required' => TRUE,
);
return $form;
}
/**
* Implements hook_form_validate
*/
function favorite_team_ctools_export_ui_form_validate(&$form , &$form_state){
//Validate code
}
/**
* Implements hook_form_submit
*/
function favorite_team_ctools_export_ui_form_submit(&$form , &$form_state){
//Submit Code
}
Al inicio debemos definir nuestra variable plugin como un array asociativo en el cual le daremos algunas indicaciones como el schema que estamos usando, los atributos de menu, la forma de como serán nombrados nuestros objetos y muy importante, la definición de formulario, así como la funciones validate y el submit del formulario.
Aunque no debemos de preocuparnos por guardar el registro, eso ya lo hace automáticamente ctools pero probablemente en algún momento la necesitamos para alguna funcionalidad especifica, debemos señalar que los atributos de nuestro nuestro formulario deben tenemos el mismo nombre usando en los campo del schema para que ctools pueda guardar el registro apropiadamente.
Por ultimo debemos activar nuestro modulo si no esta activo o borrar el cache de Ctools, para que Ctools lo reconozca y cuando accedamos a la url admin/config/people/team que definimos en el plugin observaremos que tendremos una interfaz bastante familiar.
De esta manera y con la ayuda de ctools nos hemos salvado de invertir horas haciendo operaciones básicas de crear, editar, borrar y ademas tenemos nuevas funcionalidades como clonar, deshabiitar y nuestra meta inicial poder exportarlo, solo nos restaria instalar el módulo en el sitio a donde vamos a importar nuestros objetos, también puede ser buena idea empaquetar un feature, pero esto ya depende de lo que cumpla nuestras necesidades.
Como es de esperarse en el sitio donde se importa debe existir la tabla donde se va ha importar.
Por aca les comparto un pequeño modulo de ejemplo en caso de necesitar un poco mas de información, espero haya sido de su agrado.