Mostrando entradas con la etiqueta cck. Mostrar todas las entradas
Mostrando entradas con la etiqueta cck. Mostrar todas las entradas

martes, 9 de noviembre de 2010

Los hooks del módulo CCK

El módulo Content Construction Kit (CCK) es uno de los módulos que debería tener implementada toda instalación de Drupal. Es tan imprescindible que en Drupal 7 va a ir incorporado de serie.

En Drupal la primera clasificación que tenemos es la de tipos de contenido, por defecto vienen creados el tipos de contenido historia y el tipos de contenido artículo. Estos contenidos tienen un título y un texto. Pero para poder crear tipos de contenidos más complejos y que tengan más campos aparte de estos 2, como pueden ser imágenes o fechas, será necesario utilizar el módulo CCK.

 Una vez lo hayamos hecho deberemos descargar e instalar módulos que proporcionen los tipos de campo especiales que necesitemos.Lo interesante de este sistema es que no hace falta programar una sola línea de código para crear un tipo de contenido completamente personalizado, a base de clicks de ratón podemos crear todos los tipos de contenido que requiera un gran portal.

Si nosotros como desarrolladores deseamos crear un nuevo tipo de contenido específico para nuestra aplicación, deberemos crear un módulo que utilice el API que proporciona CCK para poder crear el campo que necesitemos. El módulo CCK tiene un extenso API que principalmente se basa en distintos hooks, que son necesarios para poder crear los diferentes componentes que ofrece, como pueden ser widgets, campos y formatters. En este post hago un breve resumen de los principales hooks que ofrece este módulo. Para información más detallada se puede acudir a la documentación del módulo.





hook_field_info()

hook_field_info()
Declara información sobre un tipo de campo. Importante: El nombre del campo será truncado a 32 caracteres enla BD y arrays internos.

Parámetros

Este hook no tiene parámetros de entrada.

Retorna

Un array asociativo cuya llave es el nombre del tipo de campo. Cada elemento del array es un array con estas llaves y valores:
  •     'label': El nombre que se le mostrará al usuario del tipo de campo.

hook_field()

hook_field($op, &$node, $field, &$node_field, $teaser, $page)
Este hook define el comportamiento de un campo. En la mayoría de los casos, sólo la operación 'validate' es relevante, el resto están implementadas en content_field(), y son suficientes.

Parámetros

  •     $op, en el que se define la operación del campo que se requiere en ese momento:
    •     'load': Lo que ocurre cuando el nodo es cargado de la BD. Este hook debería ser usado para cargar el campo.
    •     'view': Lo que sucede cuando el campo es mostrado al usuario. El módulo debería preparar y devolver una cadena HTML que contenga la representación por defecto del campo. Será llamado sólo si 'view' es puesto a TRUE en el hook_field_settings('callbacks')
    •      'validate':El usuario acaba de editar el nodo y quiere ver la vista previa o enviarlo. Este hook puede usarse para comprobar o incluso modificar el nodo. Los errores deben mostrarse de la forma form_set_error().
    •      'submit': El usuario acaba de enviar el nodo y ha pasado la validación. Este hook se puede utilizar para modificar algun dato del nodo.
    •      'presave':Modificaciones en el nodo justo antes de ser guardado.
    •      'insert':El nodo está siendo creado.
    •      'update':El nodo está siendo actualizado.
    •      'delete':El nodo está siendo borrado.
  •     &$node: El nodo sobre el que se estaá actuando. Este argumento es pasado por referencia. Aconsejable no modificarlo.
  •     &$node_field:El contenido de ese campo para el nodo. Los cambios en esta variable serán guardados en el nodo.

Retorna

Esta valor varía en función del valor de '$op':
  •      $op=='load':Se debe retornar un objeto que contenga valores extra que añadir al objeto nodo.
  •     $op=='view':Una cadena HTML representando el campo 
  •     El resto de operaciones no retornan ningún valor.

hook_field_settings()

hook_field_settings($op, $field)
Maneja los parámetros de un campo.

Parámetros

  •     $op La operación a la que se refier, puede ser:
    •     'form':Muestra el formulario de configuración del campo.
    •     'validate':Comprueba la configuración del campo por posibles errores.
    •     'save':Declara que campos se deben guardar en la BD.
    •     'database columns':Declara las columnas que content.module deberá crear y manejar. Si el módulo de campo desea manejar por el mismo el almacenamiento en BD, deberá ser omitido.
    •      'callbacks:Describe el ámbito del comportamiento en relación con las operaciones del hook_field.
    •     'views data': Declara la información para Views del campo. Pueden ser tabla, argumentos, filtros... Usar este operador sólo si se quieren sobreescribir la implementación por defecto de CCK.
  •      $field: El campo sobre el que se hace la operación.

Retorna

Esto varía según el valor de $op:
  •      $op=='form': Un array de elementos de formulario para añadir a la página de configuración del campo.
  •      $op=='validate': No retorna nada. Los errores deben enviarse de la forma form_set_error().
  •     $op=='save': Un array de nombres de elementos del formulario que deben almacenarse en la BD.
  •     $op=='database columns': Un array asociativo por el nombre de la columna con arrays con la información sobre la columna. Se deben incluir los campos 'type',con el tipo de dato de MySQL para la columna, y puede incluir el campo 'sortable para indicar al módulo views uqe la columna contiene información ordenable.
  •   $op=='callbacks': Un array describiendo el comportamiento del campo respecto al comportamiento del hook_field(). El array está asociado por las acciones de hook_field()('view','validate'...)y sus posibles valores son los siguientes:
    • CONTENT_CALLBACK_NONE: No hace nada.
    • CONTENT_CALLBACK_CUSTOM: Usa el mismo comportamiento que en hook_field(operacion).
    • CONTENT_CALLBACK_DEFAULT:Usa el comportamiento por defecto.
  •     $op=='views data': Un array de tablas, argumentos y filtros utilizados por views.

hook_widget_info()

hook_widget_info()
Declara información sobre un tipo de widget. Importante: El nombre del widget será truncado a 32 caracteres enla BD y arrays internos.

Parámetros

Este hook no tiene parámetros de entrada.

Retorna

Un array asociativo cuya llave es el nombre del tipo de campo. Cada elemento del array es un array con estas llaves y valores:
  •     'label': El nombre que se le mostrará al usuario del tipo de campo.
  •     'field types': Un array con los tipos de campos a los que se puede asociar el widget.
  •     'multiple values': Pueden ser:
    • CONTENT_HANDLE_CORE (Por defecto)
    • CONTENT_HANDLE_MODULE Para manejar el caso de múltiples valores dentro del módulo.
  •    'callbacks:Un array de callbacks, para poner el valor del 'valor por defecto' a uno de los siguientes valores:
    •      CONTENT_CALLBACK_NONE: No hace nada.
    •      CONTENT_CALLBACK_CUSTOM: Usa el mismo comportamiento que en hook_field(operacion).
    •      CONTENT_CALLBACK_DEFAULT: Usa el comportamiento por defecto.
Normalmente estos 2 últimos valores se obvian y se utiliza el comportamiento por defecto.

hook_widget()

hook_widget(&$form, &$form_state, $field, $items, $delta = 0)
El hook widget() controla el comportamiento del widget, principalmente para crear y validar el formulario de edición, la operación de 'proccess form values' debería ser usada para manipular los valores antes de ser salvados

Parámetros

  •     $op, que puede tomar los siguientes valores:
    •    'prepare form values': Prepara el almacenamiento de los datos almacenados para mostrarlos en el widget.
    •    'form': El nodo está siendo editado y un formulario debe ser preparado para mostrar al usuario.
    •     'validate:El usuario acaba de editar el nodo y quiere ver la vista previa o enviarlo. Este hook puede usarse para comprobar o incluso modificar el nodo.Los errores deben mostrarse de la forma form_set_error().
    •     'proccess form values': El widget convierte los datos obtenidos al formato nativo de los datos
    •     'submit':El usuario acaba de enviar el nodo y ha pasado la validación. Este hook se puede utilizar para modificar algun dato del nodo.
  •     &$node: El nodo sobre el que se estaá actuando. Este argumento es pasado por referencia. Aconsejable no modificarlo.
  •     $field: El campo sobre el que se está actuando.
  •     &$node_field:El contenido de ese campo para el nodo. Los cambios en esta variable será guardados en el nodo.

Retorna

Depende del valor que tome $op:
  •     $op=='form': Retorna un array de elementos de formulario para mostrar.
  •     El resto de valores no retornan nada.

hook_widget_settings()

hook_widget_settings($op, $widget)
Este hoook controla el comportamiento de los datos insertados mediante el widget en cuestión. Este hook es muy parecido al hook_field_settings(), con la diferencia de que este afecta al comportamiento del widget.

Parámetros

  •     $op, que puede tomar los siguientes valores:
    •     'form':Muestra el formulario de configuración del campo.
    •     'validate':Comprueba la configuración del campo por posibles errores.
    •     'save':Declara que campos se deben guardar en la BD.
    •    'callbacks:Describe el comportamiento del campo en relación con las operaciones del hook_field.

Retorna

Esto varía según el valor de $op:
  •     $op=='form': Un array de elementos de formulario para añadir a la página de configuración del campo.
  •     $op=='validate': No retorna nada. Los errores deben enviarse de la forma form_set_error().
  •     $op=='save': Un array de nombres de elementos del formulario que deben almacenarse en la BD.
  •   $op=='callbacks': Un array describiendo el comportamiento del campo respecto al comportamiento del hook_field(). El array está asociado por las acciones de hook_field()('view','validate'...)y sus posibles valores son los siguientes:
    •        CONTENT_CALLBACK_NONE: No hace nada.
    •   CONTENT_CALLBACK_CUSTOM: Usa el mismo comportamiento que en hook_field(operacion).
    •        CONTENT_CALLBACK_DEFAULT:Usa el comportamiento por defecto.

jueves, 26 de agosto de 2010

Diseño y arquitectura del módulo CCK

La tipología de los módulos de Drupal es muy diversa, desde módulos que proporcionan foros o módulos para votar contenidos hasta módulos para poder visualizar vídeos en las páginas. Sin embargo existe un módulo esencial para prácticamente todos los desarrolladores y usuarios de Drupal, el módulo CCK (Content Construction Kit). Este módulo permite la creación de prácticamente cualquier tipo de contenido que se quiera añadir al sitio Drupal gracias a su extensa API. A partir de este módulo se han creado un gran número de módulos de contenido.
Los módulos de contenido, como su propio nombre indica, son módulos que proporcionan al usuario la posibilidad de incluir contenidos de diferente tipo a un nodo, desde un simple texto o un número hasta fotografías o información geográfica.

El crear un módulo de contenido era una labor compleja y que requería de mucho trabajo para el desarrollador, hasta que apareció el módulo CCK, que proporciona un API para poder crear módulos de tipo contenido de forma sencilla y sin ser necesario tener grandes conocimientos de la arquitectura interna del core de Drupal. Además está muy bien documentado y se pueden encontrar muchos ejemplos en la red. Por eso, este post pretende ser más una explicación de la arquitectura del módulo que un tutorial sobre su utilización. Este análisis puede resultar interesante para los desarrolladores que pretendan conocer mejor que es lo que hacen en realidad cuando añaden un campo CCK en sus páginas Drupal y una ayuda para los que quieran embarcarse en la aventura de desarrollar un módulo basado en el API de CCK.

En la documentación de Drupal sobre el módulo se puede ver el siguiente esquema de las tablas que el módulo genera en la Base de Datos para almacenar la información relativa a los campos creados utilizando el módulo CCK.

Esquema de la estructura en Base de Datos de los campos CCK


El modelo de datos de CCK se basa en 3 tablas:
  • node_type: Esta tabla es general, no es creada por CCK y contiene los datos generales de los tipos de contenido disponibles en el sitio Drupal.
  • content_node_field: En esta tabla se almacenan las definiciones del campo.
  • content_node_field: contiene la relación entre un campo y un tipo de nodo, junto con las opciones de configuración de su widget asociado.
Además de estas tablas, que son la base, cada tipo de contenido crea una tabla llamada content_type_X, siendo X el nombre del tipo de contenido, esta tabla contiene las ID de los nodos que utilizan el tipo de contenido X. También se crea la tabla content_field_X, en la que X es el nombre del campo. En ella se almacenan los datos asociados a dicho campo junto con la ID del nodo al que está asociado.

El módulo CCK proporciona a los módulos que se generan bajo su API un esquema similar al Modelo Vista Controlador. Se pueden crear 2 tipos de elementos fields (campos) y widgets. Los campos son los encargados de interactuar con el core y almacenar los datos, mientras que los widgets implementan la interface que se le muestra al usuario para crear los datos a insertar en el campo.

Los campos definen el tipo de dato que se va a almacenar, en ellos se definen los campos que se añadirán en la tabla content_field_X para almacenar los datos que se le pasen al campo, los tipos de dato que se van a almacenar en esos campos, el número máximo de datos que se pueden insertar por nodo en ese campo, si el campo es requerido, etc.

Los widgets definen la forma en la que se insertarán los datos que se almacenarán en el campo, generalmente son formularios más o menos complejos según el tipo de dato a insertar. Algunos son simples campos de texto, mientras que otros son complejos formularios anidados.

Con esta estructura, se podrán crear módulos que implementen campos, módulos que tan sólo implementen widgets o módulos completos en los que se implemente tanto el campo como el widget.

De esta manera podemos conseguir que para un mismo tipo de campo existan varios tipos de widgets, del mismo modo que podemos hacer que un mismo widget se pueda asociar a varios campos distintos.

Al mismo tiempo, el módulo que implemente el campo puede procesar los datos que le lleguen desde el widget antes de enviarlos a la Base de Datos o simplemente delegar en otros módulos (denominados módulos API) esta responsabilidad y que sean ellos los encargados de procesar y almacenar los datos en la Base de Datos.

Llegados a este punto nos encontramos con un esquema de este tipo:


Además de ofrecer la posibilidad de crear distintos campos y widgets para poder insertar los valores de los distintos campos dentro de la Base de Datos, el módulo CCK también ofrece la posibilidad a los desarrolladores de crear distintos formatters para poder mostrar esta información a la hora de visualizar el nodo.

Los formatters son las distintas opciones que CCK ofrece para poder mostrar los datos introducidos en un campo cuando se visualice el nodo al que pertenece ese campo. Los formatters extraen los valores de la Base de Datos y se encargan de procesarlos para que se puedan visualizar según el deseo del creador del formatter. Se pueden definir distintos formatters para un mismo tipo de campo, por lo que se puede adaptar fácilmente a las necesidades del diseñador del sitio Drupal, por ejemplo, para visualizar los datos geográficos existen formatters que pueden mostrar esos datos geográficos en formato texto y otros que los muestran ya procesados sobre un mapa web.

Para poder ofrecer todas estas posibilidades, el módulo CCK ofrece un API muy extensa basada en distintos hooks, de los que ya hablaré en otro post más adelante. Espero que este post os haya servido de ayuda para entender mejor el comportamiento del módulo CCK.